
/**
 * @file
 * @author
 * @date
 * @brief 显示模块的子函数，包括各界面的显示实现等
 */
#include "display_interface_240x240.h"
#include "display_ctrl.h"
#include "display_drv.h"
#include "display_font_interface_240x240.h"
#include "stdlib.h"
// #include "prj_config.h"
#include "app_trace.h"
#include "arabic_reshaper.h"
#include "arm_math.h"
#include "font_mngr.h"
#include "lfs_file_manager.h"
#include "localize.h"
#include "math.h"
#include "prj_typedef.h"
#include "utf8_to_unicode.h"
#define DISP_LOG(fmt, ...) //app_trace_log(fmt "\r\n", ##__VA_ARGS__)
static uint16_t get_color_by_gray_level(uint16_t color, uint8_t gray_level);
/*********************************************************************************************
 * @brief 获取一个整数的位数,负号占一位
 * @param [in] param1
 * @return ret
 ********************************************************************************************/
uint8_t get_num_digit(int num)
{
    uint8_t digit;
    //负号
    if (num < 0)
    {
        digit = 1;
        num = -num;
    }
    else
    {
        digit = 0;
    }

    do
    {
        digit++;
        num /= 10;
    } while (num);

    return digit;
}
static uint16_t get_filter_color(uint16_t color1, uint16_t color2);
/*********************************************************************************************
 * @brief   画点
 ********************************************************************************************/
void disp_draw_point(disp_xy_t x, disp_xy_t y, uint16_t color)
{
    if ((y >= disp_ctrl.area_start_y) && (y <= disp_ctrl.area_end_y))
    {
        disp_ctrl.disp_buff[disp_ctrl.p_buff_flag][(y - disp_ctrl.area_start_y) * OLED_SIZE_X + x] = color;
    }
}
void disp_draw_point_filter_color(disp_xy_t x, disp_xy_t y, uint16_t color)
{
    if ((y >= disp_ctrl.area_start_y) && (y <= disp_ctrl.area_end_y))
    {
        disp_ctrl.disp_buff[disp_ctrl.p_buff_flag][(y - disp_ctrl.area_start_y) * OLED_SIZE_X + x] = color;
        // disp_ctrl.disp_buff[disp_ctrl.p_buff_flag][(y - disp_ctrl.area_start_y) * OLED_SIZE_X + x] =
        //     get_filter_color(color, disp_ctrl.disp_buff[disp_ctrl.p_buff_flag][(y - disp_ctrl.area_start_y) * OLED_SIZE_X + x]);
    }
}
void disp_draw_line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color, bool filter_color)
{
    uint16_t t;
    int xerr = 0, yerr = 0, delta_x, delta_y, distance;
    int incx, incy, uRow, uCol;
    delta_x = x2 - x1; //计算坐标增量
    delta_y = y2 - y1;
    uRow = x1;
    uCol = y1;
    if (delta_x > 0)
        incx = 1; //设置单步方向
    else if (delta_x == 0)
        incx = 0; //垂直线
    else
    {
        incx = -1;
        delta_x = -delta_x;
    }
    if (delta_y > 0)
        incy = 1;
    else if (delta_y == 0)
        incy = 0; //水平线
    else
    {
        incy = -1;
        delta_y = -delta_y;
    }
    if (delta_x > delta_y)
        distance = delta_x; //选取基本增量坐标轴
    else
        distance = delta_y;
    for (t = 0; t <= distance + 1; t++) //画线输出
    {
        if (filter_color)
        {
            disp_draw_point_filter_color(uRow, uCol, color); //画点
        }
        else
        {
            disp_draw_point(uRow, uCol, color); //画点
        }

        xerr += delta_x;
        yerr += delta_y;
        if (xerr > distance)
        {
            xerr -= distance;
            uRow += incx;
        }
        if (yerr > distance)
        {
            yerr -= distance;
            uCol += incy;
        }
    }
}
void disp_draw_heart_rate_rect_filter_color(int start_x, int end_x, uint8_t *y_data, uint16_t line_color, uint16_t rect_color, uint16_t bottom_y)
{
    for (int i = start_x; i < end_x; i++)
    {
        if (y_data[i - start_x] && y_data[i - start_x + 1])
        {

            for (int j = y_data[i - start_x] + 1; j < bottom_y; j++)
            {
                disp_draw_point_filter_color(i, j, rect_color);
            }
            for (int j = y_data[i - start_x + 1] + 1; j < bottom_y; j++)
            {
                disp_draw_point_filter_color(i, j, rect_color);
            }
            disp_draw_line(i, y_data[i - start_x], i + 1, y_data[i - start_x + 1], line_color, true);
            continue;
        }
        else if (y_data[i - start_x])
        {

            for (int j = y_data[i - start_x] + 1; j < bottom_y; j++)
            {
                disp_draw_point_filter_color(i, j, rect_color);
            }
            disp_draw_point_filter_color(i, y_data[i - start_x], line_color);
            continue;
        }
    }
}
/*********************************************************************************************
 * @brief 划线
 * @warning 颜色值目前是画心率曲线的专用
 ********************************************************************************************/
void disp_draw_hr_line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
{
    // #define HR_CURVE_Y_START (82)
    // #define HR_CURVE_Y_END (217)
    // #define HR_COLOR(y) RGB565((255 - ((y - HR_CURVE_Y_START) * 255) / 135), ((y - HR_CURVE_Y_START) * 255) / 135, ((y - HR_CURVE_Y_START) * 200) / 135) //心率线的颜色
    // #define HR_COLOR(y) 0xe002
    // const uint16_t hr_color_tab[]={0x7d4,0x9408,0xf920};//心率颜色值9档 135/15
    disp_draw_line(x1, y1, x2, y2, 0xe002, false);
}
#if defined(BOARD_G33)
/*********************************************************************************************
 * @brief 划线
 * @warning 颜色值目前是画心率曲线的专用
 ********************************************************************************************/
void disp_draw_gps_locus_line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
{
#define GPS_LOCUS_CURVE_Y_START (58)
#define GPS_LOCUS_CURVE_Y_H (180)
#define GPS_LOCUS_CURVE_Y_END (58 + 180)
#define GPS_LOCUS_COLOR(y)                                                                                                                   \
    RGB565((255 - ((y - GPS_LOCUS_CURVE_Y_START) * 255) / GPS_LOCUS_CURVE_Y_H), ((y - GPS_LOCUS_CURVE_Y_START) * 255) / GPS_LOCUS_CURVE_Y_H, \
           ((y - GPS_LOCUS_CURVE_Y_START) * 200) / GPS_LOCUS_CURVE_Y_H) //心率线的颜色

    // const uint16_t hr_color_tab[]={0x7d4,0x9408,0xf920};//心率颜色值9档 135/15
    uint16_t t;
    int xerr = 0, yerr = 0, delta_x, delta_y, distance;
    int incx, incy, uRow, uCol;
    delta_x = x2 - x1; //计算坐标增量
    delta_y = y2 - y1;
    uRow = x1;
    uCol = y1;
    if (delta_x > 0)
        incx = 1; //设置单步方向
    else if (delta_x == 0)
        incx = 0; //垂直线
    else
    {
        incx = -1;
        delta_x = -delta_x;
    }
    if (delta_y > 0)
        incy = 1;
    else if (delta_y == 0)
        incy = 0; //水平线
    else
    {
        incy = -1;
        delta_y = -delta_y;
    }
    if (delta_x > delta_y)
        distance = delta_x; //选取基本增量坐标轴
    else
        distance = delta_y;
    for (t = 0; t <= distance + 1; t++) //画线输出
    {
        disp_draw_point(uRow, uCol, GPS_LOCUS_COLOR(uCol)); //画点
        xerr += delta_x;
        yerr += delta_y;
        if (xerr > distance)
        {
            xerr -= distance;
            uRow += incx;
        }
        if (yerr > distance)
        {
            yerr -= distance;
            uCol += incy;
        }
    }
}
#endif
/*********************************************************************************************
* @brief   显示字库字符串
 * @param [in] x ,y 字符起点
    @param [in] p_str 字符串
    @param [in] size  尺寸(8或16)
    @return 本次刷新完成显示的字符个数
* @warning  自动换行,为了提升显示速度，只显示一行
 ********************************************************************************************/
uint32_t disp_show_font_string(int x1, int y1, int x2, int y2, uint16_t const *unicode_str, uint16_t reserve_size, int16_t *align_type)
{
    // uint8_t     utf8_len;
    // uint32_t   gb_code;
    uint8_t *dot_buff;
    int width;
    // uint8_t     *p_str_in;
    // uint8_t     *p_str_finish;
    uint16_t const *unicode_str_in = 0;
    uint16_t const *unicode_str_finish = 0;

    uint16_t *p_disp_buff; //指向要填充的位置
    uint8_t invalid_flag;
    int x_start;
    uint8_t valid_line_flag;      //标记当前解析的行和刷新的区域有没有重合区域，不重合则跳过
    int icon_start_y, icon_end_y; //标记ICON需要显示的范围
    uint16_t over_y;

    //#warning "倒着刷有问题,需要改为统一一次计算分开索引"
    if ((disp_ctrl.area_end_y < y1) || (*unicode_str == '\0'))
    {
        return 0;
    }
    // p_str_in = (uint8_t*)p_str;
    // p_str_finish = (uint8_t*)p_str;
    unicode_str_in = unicode_str;
    unicode_str_finish = unicode_str;
    invalid_flag = 0;
    x_start = x1;
    over_y = 0;

    extern_font_char_info_t font_temp;
    if (extern_font_is_valid() == false) //假如字库打不开不显示
    {
        return 0;
    }
    dot_buff = font_temp.data;

    if (y1 >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y1 - disp_ctrl.area_start_y) * OLED_SIZE_X; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag]; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y1;
    }
    if (disp_ctrl.area_end_y >= (y1 + FONT_SIZE - 1))
    {
        icon_end_y = FONT_SIZE - 1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y1;
    }
    valid_line_flag = (disp_ctrl.area_start_y < (y1 + FONT_SIZE)); //判断和要显示的区域是否有重叠区域
    uint16_t last_code = 0;
    while (*unicode_str_in != '\0')
    {
        if (last_code == '\x0A')
        {
            *align_type = get_string_align_type(unicode_str_in);
        }
        last_code = *unicode_str_in;
        if (*unicode_str_in < 0x20) //特殊意义符号
        {
            if (*unicode_str_in == '\x0A') //换行符
            {
                unicode_str_in++;
                x1 = x_start;
                y1 += FONT_SIZE + FONT_SIZE_VERTICAL_INTERVAL; // 16x16的显示每次跳2行
                if (y1 >= (y2 - FONT_SIZE))
                {
                    break;
                }
                if (disp_ctrl.area_end_y < y1)
                {
                    if (disp_ctrl.area_end_y == (y1 - 1))
                    {
                        unicode_str_finish = unicode_str_in;
                        over_y++;
                    }
                    break;
                }
                if (y1 >= disp_ctrl.area_start_y)
                {
                    p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y1 - disp_ctrl.area_start_y) * OLED_SIZE_X; //指向要填充的位置
                    icon_start_y = 0;
                }
                else
                {
                    p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag]; //指向要填充的位置
                    icon_start_y = disp_ctrl.area_start_y - y1;
                }
                if (disp_ctrl.area_end_y >= (y1 + FONT_SIZE - 1))
                {
                    icon_end_y = FONT_SIZE - 1;
                }
                else
                {
                    icon_end_y = disp_ctrl.area_end_y - y1;
                }
                unicode_str_finish = unicode_str_in;
                over_y++;
                valid_line_flag = (disp_ctrl.area_start_y < (y1 + FONT_SIZE)); //判断和要显示的区域是否有重叠区域
            }
            else //其他特殊字符跳过（包括回车0x0d等）
            {
                unicode_str_in++;
            }
            continue;
        }
        //增加空格的处理，一个2006-强转为空格-某个软件消息推送的空格是这个字符
        if ((*unicode_str_in == 0x20) || ((*unicode_str_in >= 0x2000) && (*unicode_str_in <= 0x200F)))
        {
            width = FONT_SIZE / 2;
            memset(font_temp.data, 0, sizeof(font_temp.data));
        }
        else
        {
            extern_font_get_bit_map(*unicode_str_in, &font_temp);
            width = font_temp.width;
        }
        if (width == 0)
        {
            // DISP_LOG("width == 0,utf8_len=%d",utf8_len);
            if (invalid_flag) //处理方框不连续,跳过不显示
            {
                ++unicode_str_in;
                continue;
            }
            else
            {
                // 遇到字库不存在的字符，显示"口"
                memcpy(dot_buff, ICON_FONT_LIB_UNDEFINE, 32);
                width = 16;
                invalid_flag = 1;
            }
        }
        else
        {
            invalid_flag = 0;
        }

        if (y1 > (y2 - FONT_SIZE * 2)) //末行需要预留空间
        {
            if ((width + x1) > x2 - reserve_size)
            {
                break; //显示溢出
            }
        }
        else if ((width + x1) > x2)
        {
            x1 = x_start;
            y1 += FONT_SIZE + FONT_SIZE_VERTICAL_INTERVAL; // 16x16的显示每次跳2行
            if (y1 >= (y2 - FONT_SIZE))
            {
                break;
            }
            if (disp_ctrl.area_end_y < y1)
            {
                if (disp_ctrl.area_end_y == (y1 - 1))
                {
                    unicode_str_finish = unicode_str_in;
                    over_y++;
                }
                break;
            }
            if (y1 >= disp_ctrl.area_start_y)
            {
                p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y1 - disp_ctrl.area_start_y) * OLED_SIZE_X; //指向要填充的位置
                icon_start_y = 0;
            }
            else
            {
                p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag]; //指向要填充的位置
                icon_start_y = disp_ctrl.area_start_y - y1;
            }
            if (disp_ctrl.area_end_y >= (y1 + FONT_SIZE - 1))
            {
                icon_end_y = FONT_SIZE - 1;
            }
            else
            {
                icon_end_y = disp_ctrl.area_end_y - y1;
            }
            unicode_str_finish = unicode_str_in;
            over_y++;
            valid_line_flag = (disp_ctrl.area_start_y < (y1 + FONT_SIZE)); //判断和要显示的区域是否有重叠区域
        }
        if (valid_line_flag)
        {
            uint16_t *p_disp_temp = 0;
            if (*align_type == align_type_right)
            {
                p_disp_temp = p_disp_buff + x1;
            }
            else
            {
                int offset = x1 - x_start;
                p_disp_temp = p_disp_buff + x2 - offset - width;
            }
            //展开16*16字体
            if (icon_start_y < 8) //第一行
            {
                uint8_t b = icon_end_y > 7 ? 7 : icon_end_y;
                for (uint8_t a = icon_start_y; a <= b; a++)
                {
                    uint8_t offset = 1 << a;
                    for (uint8_t i = 0; i < width; i++)
                    {
                        if (dot_buff[i] & offset)
                        {
                            p_disp_temp[i] = RGB565_COLOR_WHITE;
                        }
                    }
                    p_disp_temp += OLED_SIZE_X;
                }
            }
            if ((icon_start_y < 16) & (icon_end_y >= 8)) //第二行
            {
                uint8_t b = icon_end_y > 15 ? 15 : icon_end_y;
                for (uint8_t a = icon_start_y > 8 ? icon_start_y : 8; a <= b; a++)
                {
                    uint8_t offset = 1 << (a - 8);
                    for (uint8_t i = 0; i < width; i++)
                    {
                        if (dot_buff[i + FONT_SIZE] & offset)
                        {
                            p_disp_temp[i] = RGB565_COLOR_WHITE;
                        }
                    }
                    p_disp_temp += OLED_SIZE_X;
                }
            }
            if (icon_end_y >= 16) //第三行
            {
                for (uint8_t a = icon_start_y > 16 ? icon_start_y : 16; a <= icon_end_y; a++)
                {
                    uint8_t offset = 1 << (a - 16);
                    for (uint8_t i = 0; i < width; i++)
                    {
                        if (dot_buff[i + FONT_SIZE * 2] & offset)
                        {
                            p_disp_temp[i] = RGB565_COLOR_WHITE;
                        }
                    }
                    p_disp_temp += OLED_SIZE_X;
                }
            }
        }
        x1 += width + FONT_SIZE_HORIZ_INTERVAL;
        unicode_str_in++;
    }
    if ((*unicode_str_in == '\0') && (icon_end_y >= (FONT_SIZE - 1))) //显示完成
    {
        unicode_str_finish = unicode_str_in;
    }

    return ((uint8_t *)unicode_str_finish - (uint8_t *)unicode_str) | (over_y << 16);
}

/*********************************************************************************************
* @brief   显示字库utf8-限制20字节内的短字符串
 * @param [in] x ,y 字符起点
    @param [in] p_str 字符串
* @warning
 ********************************************************************************************/
void disp_show_font_string_utf8(uint8_t x, uint8_t y, const char *str, uint8_t reserve_size)
{
    disp_show_font_string_utf8_area(x, y, OLED_SIZE_X, OLED_SIZE_Y, str, reserve_size);
}

void disp_show_font_string_utf8_area(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, const char *str, uint8_t reserve_size)
{
    uint8_t buff[120] = {0};
    int16_t align = align_type_right;
    utf8_string_to_unicode_string((const uint8_t *)str, buff, sizeof(buff));
    align = arabic_reshaper((uint16_t *)buff);
    disp_show_font_string(x1, y1, x2, y2, (uint16_t *)buff, reserve_size, &align);
}
//居中显示字符串
/*********************************************************************************************
* @brief   居中显示字库utf8-限制20字节内的短字符串
 * @param [in]y 字符起点
    @param [in] p_str 字符串
* @warning
 ********************************************************************************************/
void disp_show_font_string_utf8_mid(uint8_t y, const char *str, uint8_t reserve_size)
{
    uint8_t buff[120] = {0};
    int16_t align = align_type_right;
    int x = disp_calc_font_string_start_x(DISP_NUM_TYPE_MID, OLED_SIZE_X / 2 - 1, str, 24);
    utf8_string_to_unicode_string((const uint8_t *)str, buff, sizeof(buff));
    align = arabic_reshaper((uint16_t *)buff);
    disp_show_font_string(x, y, OLED_SIZE_X - x - 1, y + 24 - 1, (uint16_t *)buff, reserve_size, &align);
}

/*********************************************************************************************
* @brief   计算输入的字符串一页能被显示多少
 * @param [in] x ,y 字符起点
    @param [in] p_str 字符串
    @param
* @warning  计算偏移用的，没有显示效果
 ********************************************************************************************/
int disp_show_font_string_page_cal(int x1, int y1, int x2, int y2, uint16_t const *unicode_str, uint16_t reserve_size)
{
    // uint8_t     utf8_len = 0;
    // uint32_t   gb_code = 0;
    uint8_t width;
    uint16_t const *unicode_str_in = unicode_str;
    uint8_t invalid_flag = 0;
    uint8_t x_start = x1;
    uint16_t disp_width = 0;

    extern_font_char_info_t font_temp;
    if (extern_font_is_valid() == false) //假如字库打不开不显示
    {
        return 0;
    }

    while (*unicode_str_in != '\0')
    {
        if (*unicode_str_in < 0x20) //特殊意义符号
        {
            if (*unicode_str_in == '\x0A') //换行符
            {
                unicode_str_in++;
                x1 = x_start;
                y1 += FONT_SIZE + FONT_SIZE_VERTICAL_INTERVAL; // 16x16的显示每次跳2行
                // if (y1 >= (OLED_SIZE_Y - FONT_SIZE))
                if (y1 >= (y2 - FONT_SIZE))
                {
                    break;
                }
            }
            else //其他特殊字符跳过（包括回车0x0d等）
            {
                unicode_str_in++;
            }
            continue;
        }

        extern_font_get_bit_map(*unicode_str_in, &font_temp);
        width = font_temp.width;

        if (width == 0)
        {
            // DISP_LOG("width == 0");
            if (invalid_flag) //处理方框不连续,跳过不显示
            {
                // p_str_in += utf8_len;
                unicode_str_in++;
                continue;
            }
            else
            {
                // 遇到字库不存在的字符，显示"口"
                width = 16;
                invalid_flag = 1;
            }
        }
        else
        {
            invalid_flag = 0;
        }

        // if (y1 >= (OLED_SIZE_Y - FONT_SIZE * 2)) //末行需要预留空间
        if (y1 >= (y2 - FONT_SIZE * 2)) //末行需要预留空间
        {
            // if ((width + x1) > OLED_SIZE_X - reserve_size)
            if ((width + x1) > x2 - reserve_size)
            {
                break; //显示溢出
            }
        }
        // else if ((width + x1) > OLED_SIZE_X)
        else if ((width + x1) > x2)
        {
            x1 = x_start;
            y1 += FONT_SIZE + FONT_SIZE_VERTICAL_INTERVAL; // 16x16的显示每次跳2行
        }
        x1 += width + FONT_SIZE_HORIZ_INTERVAL;
        disp_width += width + FONT_SIZE_HORIZ_INTERVAL;
        // p_str_in += utf8_len;
        unicode_str_in++;
    }

    return ((uint8_t *)unicode_str_in - (uint8_t *)unicode_str) | (disp_width << 16);
}

/*********************************************************************************************
 * @brief 颜色透明混合
 * @param [in] gray_level 0~31
 * @warning
 ********************************************************************************************/
static uint16_t get_color_mixture(uint16_t color1, uint16_t color2)
{
    uint8_t red, green, blue;
    if (color2 == 0)
    {
        return color1;
    }
    blue = 31 - (31 - color1 & 0x1F) * (31 - color2 & 0x1F) / 31;
    green = 63 - (63 - (color1 >> 5) & 0x3F) * (63 - (color2 >> 5) & 0x3F) / 63;
    red = 31 - (31 - (color1 >> 11) & 0x1F) * (31 - (color2 >> 11) & 0x1F) / 31;
    return (red << 11) | (green << 5) | (blue);
}
/*********************************************************************************************
 * @brief 颜色半透明混合
 * @warning
 ********************************************************************************************/
static uint16_t get_color_mixture2(uint16_t color1, uint16_t color2)
{
    uint16_t red, green, blue;

    blue = (RGB565_GET_COLOR_B(color1) + RGB565_GET_COLOR_B(color2)) >> 1;
    green = (RGB565_GET_COLOR_G(color1) + RGB565_GET_COLOR_G(color2)) >> 1;
    red = (RGB565_GET_COLOR_R(color1) + RGB565_GET_COLOR_R(color2)) >> 1;
    return (red << 11) | (green << 5) | (blue);
}
/*********************************************************************************************
 * @brief 颜色混合
 * @warning
 ********************************************************************************************/
static uint16_t get_color_mixture3(uint16_t color1, uint16_t color2)
{
    uint16_t red, green, blue;

    blue = RGB565_GET_COLOR_B(color1) + (31 - RGB565_GET_COLOR_B(color1)) * RGB565_GET_COLOR_B(color2) / 31;

    green = RGB565_GET_COLOR_G(color1) + (63 - RGB565_GET_COLOR_G(color1)) * RGB565_GET_COLOR_G(color2) / 63;

    red = RGB565_GET_COLOR_R(color1) + (31 - RGB565_GET_COLOR_R(color1)) * RGB565_GET_COLOR_R(color2) / 31;

    if (blue > 31)
    {
        blue = 31;
    }
    if (green > 63)
    {
        green = 63;
    }
    if (red > 31)
    {
        red = 31;
    }
    uint16_t ret = (red << 11) | (green << 5) | (blue);
    return ret;
}
static uint16_t get_multiply_color(uint16_t color1, uint16_t color2)
{
    if (color1 == 0xffdf)
    {
        color1 = 0xffff;
    }
    uint16_t red = 0;
    uint16_t green = 0;
    uint16_t blue = 0;
    red = RGB565_GET_COLOR_R(color1) * RGB565_GET_COLOR_R(color2) / 31;
    green = RGB565_GET_COLOR_G(color1) * RGB565_GET_COLOR_G(color2) / 63;
    blue = RGB565_GET_COLOR_B(color1) * RGB565_GET_COLOR_B(color2) / 31;
    if (blue > 31)
    {
        blue = 31;
    }
    if (green > 63)
    {
        green = 63;
    }
    if (red > 31)
    {
        red = 31;
    }
    uint16_t ret = (red << 11) | (green << 5) | (blue);
    return ret;
}

static uint16_t get_filter_color(uint16_t color1, uint16_t color2)
{
    uint16_t red = 0;
    uint16_t green = 0;
    uint16_t blue = 0;
    blue = 31 - ((31 - RGB565_GET_COLOR_B(color1)) * (31 - RGB565_GET_COLOR_B(color2))) / 31;
    green = 63 - ((63 - RGB565_GET_COLOR_G(color1)) * (63 - RGB565_GET_COLOR_G(color2))) / 63;
    red = 31 - ((31 - RGB565_GET_COLOR_R(color1)) * (31 - RGB565_GET_COLOR_R(color2))) / 31;
    if (blue > 31)
    {
        blue = 31;
    }
    if (green > 63)
    {
        green = 63;
    }
    if (red > 31)
    {
        red = 31;
    }
    uint16_t ret = (red << 11) | (green << 5) | (blue);
    return ret;
}
// color transparency_by_white false = 黑色表示透明，白色表示完全
static uint16_t transparency_anti_aliasing(uint16_t color, uint16_t back, uint16_t solid_colour, bool transparency_by_white)
{
    // uint16_t red = 0;
    // uint16_t green = 0;
    // uint16_t blue = 0;
    // float transparency[3] = {0.f, 0.f, 0.f};
    uint16_t const color_rgb[3] = {RGB565_GET_COLOR_R(color), RGB565_GET_COLOR_G(color), RGB565_GET_COLOR_B(color)};
    uint16_t const solid_rgb[3] = {RGB565_GET_COLOR_R(solid_colour), RGB565_GET_COLOR_G(solid_colour), RGB565_GET_COLOR_B(solid_colour)};
    uint16_t const max_rgb[3] = {31, 63, 31};
    uint16_t result_rgb[3] = {0};
    int transparency_index = 0; //选定RGB最大的那个数，来做透明度
    {
        uint16_t max_rgb = 0;
        uint16_t min_rgb = 0xFFFF;
        for (int i = 0; i < 3; i++)
        {
            if (transparency_by_white)
            {
                if (min_rgb > solid_rgb[i])
                {
                    min_rgb = solid_rgb[i];
                    transparency_index = i;
                }
            }
            else
            {
                if (max_rgb < solid_rgb[i])
                {
                    max_rgb = solid_rgb[i];
                    transparency_index = i;
                }
            }
        }
    }
    float transparency = 0.f;
    if (transparency_by_white)
    {
        if (color_rgb[transparency_index] < solid_rgb[transparency_index])
        {
            transparency = 1.f;
        }
        else if (solid_rgb[transparency_index] != max_rgb[transparency_index])
        {
            transparency = ((float)(max_rgb[transparency_index] - color_rgb[transparency_index])) / (max_rgb[transparency_index] - solid_rgb[transparency_index]);
        }
    }
    else
    {
        if (color_rgb[transparency_index] > solid_rgb[transparency_index])
        {
            transparency = 1.f;
        }
        else if (solid_rgb[transparency_index] != 0)
        {
            transparency = (float)color_rgb[transparency_index] / solid_rgb[transparency_index];
        }
    }
    uint16_t const back_rgb[3] = {RGB565_GET_COLOR_R(back), RGB565_GET_COLOR_G(back), RGB565_GET_COLOR_B(back)};
    for (int i = 0; i < 3; i++)
    {
        result_rgb[i] = back_rgb[i] + ((int)solid_rgb[i] - back_rgb[i]) * transparency;
        if (result_rgb[i] > max_rgb[i])
        {
            result_rgb[i] = max_rgb[i];
        }
    }
    uint16_t ret = (result_rgb[0] << 11) | (result_rgb[1] << 5) | (result_rgb[2]);
    return ret;
    // float transparency_max = 0.f;
    // if (transparency_by_white)
    // {
    //     if (RGB565_GET_COLOR_R(color) < RGB565_GET_COLOR_R(solid_colour))
    //     {
    //         transparency[0] = 1.f;
    //     }
    //     else if (RGB565_GET_COLOR_R(solid_colour) != 31)
    //     {
    //         transparency[0] = (31 - (float)RGB565_GET_COLOR_R(color)) / (31 - RGB565_GET_COLOR_R(solid_colour));
    //     }

    //     if (RGB565_GET_COLOR_G(color) < RGB565_GET_COLOR_G(solid_colour))
    //     {
    //         transparency[1] = 1.f;
    //     }
    //     else if (RGB565_GET_COLOR_G(solid_colour) != 63)
    //     {
    //         transparency[1] = (63 - (float)RGB565_GET_COLOR_G(color)) / (63 - RGB565_GET_COLOR_G(solid_colour));
    //     }

    //     if (RGB565_GET_COLOR_B(color) < RGB565_GET_COLOR_B(solid_colour))
    //     {
    //         transparency[2] = 1.f;
    //     }
    //     else if (RGB565_GET_COLOR_B(solid_colour) != 31)
    //     {
    //         transparency[2] = (31 - (float)RGB565_GET_COLOR_B(color)) / (31 - RGB565_GET_COLOR_B(solid_colour));
    //     }
    // }
    // else
    // {
    //     if (RGB565_GET_COLOR_R(color) > RGB565_GET_COLOR_R(solid_colour))
    //     {
    //         transparency[0] = 1.f;
    //     }
    //     else if (RGB565_GET_COLOR_R(solid_colour) != 0)
    //     {
    //         transparency[0] = (float)RGB565_GET_COLOR_R(color) / RGB565_GET_COLOR_R(solid_colour);
    //     }

    //     if (RGB565_GET_COLOR_G(color) > RGB565_GET_COLOR_G(solid_colour))
    //     {
    //         transparency[1] = 1.f;
    //     }
    //     else if (RGB565_GET_COLOR_G(solid_colour) != 0)
    //     {
    //         transparency[1] = (float)RGB565_GET_COLOR_G(color) / RGB565_GET_COLOR_G(solid_colour);
    //     }

    //     if (RGB565_GET_COLOR_B(color) > RGB565_GET_COLOR_B(solid_colour))
    //     {
    //         transparency[2] = 1.f;
    //     }
    //     else if (RGB565_GET_COLOR_B(solid_colour) != 0)
    //     {
    //         transparency[2] = (float)RGB565_GET_COLOR_B(color) / RGB565_GET_COLOR_B(solid_colour);
    //     }
    // }

    // if (color == 0xF800)
    // {
    //     red = 31;
    // }
    // else if (color == 0xF8A2)
    // {
    //     red = 31;
    // }
    // else if (color == 0)
    // {
    //     red = 31;
    // }
    // for(int i = 0; i< 3; i++)
    // {
    //     result_rgb[i] =
    // }
    // red = (int)RGB565_GET_COLOR_R(back) + ((int)RGB565_GET_COLOR_R(solid_colour) - RGB565_GET_COLOR_R(back)) * transparency[0];   // RGB565_GET_COLOR_R(color) / RGB565_GET_COLOR_R(solid_colour);
    // green = (int)RGB565_GET_COLOR_G(back) + ((int)RGB565_GET_COLOR_G(solid_colour) - RGB565_GET_COLOR_G(back)) * transparency[1]; // RGB565_GET_COLOR_G(color) / RGB565_GET_COLOR_G(solid_colour);
    // blue = (int)RGB565_GET_COLOR_B(back) + ((int)RGB565_GET_COLOR_B(solid_colour) - RGB565_GET_COLOR_B(back)) * transparency[2];  // RGB565_GET_COLOR_B(color) / RGB565_GET_COLOR_B(solid_colour);
    // if (red > 31)
    // {
    //     red = 31;
    // }
    // if (green > 63)
    // {
    //     green = 63;
    // }
    // if (blue > 31)
    // {
    //     blue = 31;
    // }
    // uint16_t ret = (red << 11) | (green << 5) | (blue);
    // return ret;
    // if (RGB565_GET_COLOR_R(back) > 15 && RGB565_GET_COLOR_G(back) > 31 && RGB565_GET_COLOR_B(back) > 15)
    // {
    //     uint16_t red = 31 - RGB565_GET_COLOR_R(color) * (31 - RGB565_GET_COLOR_R(solid_colour)) / RGB565_GET_COLOR_R(solid_colour);
    //     uint16_t green = 63 - RGB565_GET_COLOR_G(color) * (63 - RGB565_GET_COLOR_G(solid_colour)) / RGB565_GET_COLOR_G(solid_colour);
    //     uint16_t blue = 31 - RGB565_GET_COLOR_B(color) * (31 - RGB565_GET_COLOR_B(solid_colour)) / RGB565_GET_COLOR_B(solid_colour);
    //     if (blue > 31)
    //     {
    //         blue = 31;
    //     }
    //     if (green > 63)
    //     {
    //         green = 63;
    //     }
    //     if (red > 31)
    //     {
    //         red = 31;
    //     }
    //     uint16_t new_color = (red << 11) | (green << 5) | (blue);
    //     return get_multiply_color(back, new_color);
    //     // return new_color;
    //     //白底
    //     // red = RGB565_GET_COLOR_B(back) * RGB565_GET_COLOR_B(color) / 31 + transparency_red*RGB565_GET_COLOR_R(color);
    //     // green = RGB565_GET_COLOR_B(back) * RGB565_GET_COLOR_B(color) / 31 +;
    //     // blue = RGB565_GET_COLOR_B(back) * RGB565_GET_COLOR_B(color) / 31 + ;
    //     // return back;
    // }
    // else
    // {
    //     //黑底
    //     return get_filter_color(color, back);
    //     // red = transparency_red * RGB565_GET_COLOR_R(solid_colour);
    // }
}
void disp_draw_user_image_filter_color_gray_lucency(int16_t x, int16_t y, const uint8_t *p_user_image, uint16_t color)
{
    uint16_t width, height;
    uint16_t color_number;
    uint16_t *color_tab = (uint16_t *)(p_user_image + 6);
    width = p_user_image[0] + (p_user_image[1] << 8);
    height = p_user_image[2] + (p_user_image[3] << 8);
    color_number = p_user_image[4] + (p_user_image[5] << 8);
    p_user_image += color_number * 2 + 6; //指向数据

    uint16_t last_color = color_tab[0];
    uint16_t same_color_cnt = 0;
    uint16_t image_data_index = 0;
    uint8_t addr_out_flag;

    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y + height - 1)) || (disp_ctrl.area_end_y < y))
    {
        return;
    }

    uint16_t *p_disp_buff;
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y - disp_ctrl.area_start_y) * OLED_SIZE_X + x; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + x; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y;
    }
    if (disp_ctrl.area_end_y >= (y + height - 1))
    {
        icon_end_y = height - 1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y;
    }

    //依次填充数据
    if (color_number <= 127)
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] & 0x80)
            {
                same_color_cnt = (p_user_image[image_data_index] & 0x7F);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            addr_out_flag = 0;
            for (uint16_t j = 0; j < width; j++)
            {
                if (((j + x) < 0) || ((j + x) >= OLED_SIZE_X)) //地址溢出的不处理
                {
                    addr_out_flag |= 2;
                }
                else
                {
                    addr_out_flag &= ~2;
                }
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = get_filter_color(get_color_by_gray_level(color, last_color & 0x1F), p_disp_buff[j]);
                    }
                    continue;
                }

                if (p_user_image[image_data_index] & 0x80)
                {
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = get_filter_color(get_color_by_gray_level(color, last_color & 0x1F), p_disp_buff[j]);
                    }
                    same_color_cnt = (p_user_image[image_data_index] & 0x7F) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]];
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = get_filter_color(get_color_by_gray_level(color, last_color & 0x1F), p_disp_buff[j]);
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
    else
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] == 0xFF)
            {
                image_data_index++;
                same_color_cnt = (p_user_image[image_data_index]);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            addr_out_flag = 0;
            for (uint16_t j = 0; j < width; j++)
            {
                if (((j + x) < 0) || ((j + x) >= OLED_SIZE_X)) //地址溢出的不处理
                {
                    addr_out_flag |= 2;
                }
                else
                {
                    addr_out_flag &= ~2;
                }
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = get_filter_color(get_color_by_gray_level(color, last_color & 0x1F), p_disp_buff[j]);
                    }
                    continue;
                }

                if (p_user_image[image_data_index] == 0xFF)
                {
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = get_filter_color(get_color_by_gray_level(color, last_color & 0x1F), p_disp_buff[j]);
                    }
                    image_data_index++;
                    same_color_cnt = (p_user_image[image_data_index]) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]];
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = get_filter_color(get_color_by_gray_level(color, last_color & 0x1F), p_disp_buff[j]);
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
}
/*********************************************************************************************
 * @brief 画自定义图片格式
 * @param [in] param1
 * @param [out] param2
 * @return ret
 * @note
 * @warning
 ********************************************************************************************/
void disp_draw_user_image_filter_color(int16_t x, int16_t y, const uint8_t *p_user_image)
{
    uint16_t width, height;
    uint16_t color_number;
    uint16_t *color_tab = (uint16_t *)(p_user_image + 6);
    width = p_user_image[0] + (p_user_image[1] << 8);
    height = p_user_image[2] + (p_user_image[3] << 8);
    color_number = p_user_image[4] + (p_user_image[5] << 8);
    p_user_image += color_number * 2 + 6; //指向数据

    uint16_t last_color = color_tab[0];
    uint16_t same_color_cnt = 0;
    uint16_t image_data_index = 0;
    uint8_t addr_out_flag;

    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y + height - 1)) || (disp_ctrl.area_end_y < y))
    {
        return;
    }

    uint16_t *p_disp_buff;
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y - disp_ctrl.area_start_y) * OLED_SIZE_X + x; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + x; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y;
    }
    if (disp_ctrl.area_end_y >= (y + height - 1))
    {
        icon_end_y = height - 1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y;
    }

    //依次填充数据
    if (color_number <= 127)
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] & 0x80)
            {
                same_color_cnt = (p_user_image[image_data_index] & 0x7F);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            addr_out_flag = 0;
            for (uint16_t j = 0; j < width; j++)
            {
                if (((j + x) < 0) || ((j + x) >= OLED_SIZE_X)) //地址溢出的不处理
                {
                    addr_out_flag |= 2;
                }
                else
                {
                    addr_out_flag &= ~2;
                }
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = get_filter_color(last_color, p_disp_buff[j]);
                    }
                    continue;
                }

                if (p_user_image[image_data_index] & 0x80)
                {
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = get_filter_color(last_color, p_disp_buff[j]);
                    }
                    same_color_cnt = (p_user_image[image_data_index] & 0x7F) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]];
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = get_filter_color(last_color, p_disp_buff[j]);
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
    else
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] == 0xFF)
            {
                image_data_index++;
                same_color_cnt = (p_user_image[image_data_index]);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            addr_out_flag = 0;
            for (uint16_t j = 0; j < width; j++)
            {
                if (((j + x) < 0) || ((j + x) >= OLED_SIZE_X)) //地址溢出的不处理
                {
                    addr_out_flag |= 2;
                }
                else
                {
                    addr_out_flag &= ~2;
                }
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = get_filter_color(last_color, p_disp_buff[j]);
                    }
                    continue;
                }

                if (p_user_image[image_data_index] == 0xFF)
                {
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = get_filter_color(last_color, p_disp_buff[j]);
                    }
                    image_data_index++;
                    same_color_cnt = (p_user_image[image_data_index]) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]];
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = get_filter_color(last_color, p_disp_buff[j]);
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
}

typedef struct __point_info_t
{
    uint16_t *point;
    int x;
    int y;
    uint16_t color;
    void const *draw_ext_para;
} point_info_t;
typedef void (*draw_point_callback)(point_info_t const *point_info_t);
void disp_draw_user_image_ext(int16_t x, int16_t y, const uint8_t *p_user_image, draw_point_callback callback, void const *draw_ext_para)
{
#define DISP_POINT_INFO_CALL                \
    do                                      \
    {                                       \
        point_info_t const info = {         \
            .point = &p_disp_buff[j],       \
            .x = j + x,                     \
            .y = i + y,                     \
            .color = last_color,            \
            .draw_ext_para = draw_ext_para, \
        };                                  \
        callback(&info);                    \
    } while (0)
    /*图片格式
    uint16_t  width;
    uint16_t  height;
    uint16_t  color_tab_size;       //最大254
    uint16_t  color_tab[];              //颜色表
    uint8_t    color_index[];           //颜色数据的序号，最高位为1时代表有n个与前面一个相同颜色的点（不包含前面那个颜色）
    */
    uint16_t width, height;
    uint16_t color_number;
    uint16_t *color_tab = (uint16_t *)(p_user_image + 6);
    width = p_user_image[0] + (p_user_image[1] << 8);
    height = p_user_image[2] + (p_user_image[3] << 8);
    color_number = p_user_image[4] + (p_user_image[5] << 8);
    p_user_image += color_number * 2 + 6; //指向数据

    uint16_t last_color = color_tab[0];
    uint16_t same_color_cnt = 0;
    uint16_t image_data_index = 0;
    uint8_t addr_out_flag;

    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y + height - 1)) || (disp_ctrl.area_end_y < y))
    {
        return;
    }

    uint16_t *p_disp_buff = 0;
    uint8_t icon_start_y = 0;
    uint8_t icon_end_y = 0; //标记ICON需要显示的范围
    if (y >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y - disp_ctrl.area_start_y) * OLED_SIZE_X + x; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + x; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y;
    }
    if (disp_ctrl.area_end_y >= (y + height - 1))
    {
        icon_end_y = height - 1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y;
    }

    //依次填充数据
    if (color_number <= 127)
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] & 0x80)
            {
                same_color_cnt = (p_user_image[image_data_index] & 0x7F);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            addr_out_flag = 0;
            for (uint16_t j = 0; j < width; j++)
            {
                if (((j + x) < 0) || ((j + x) >= OLED_SIZE_X)) //地址溢出的不处理
                {
                    addr_out_flag |= 2;
                }
                else
                {
                    addr_out_flag &= ~2;
                }
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    if (addr_out_flag == 0)
                    {
                        DISP_POINT_INFO_CALL;
                        // p_disp_buff[j] = last_color;
                    }
                    continue;
                }

                if (p_user_image[image_data_index] & 0x80)
                {
                    if (addr_out_flag == 0)
                    {
                        DISP_POINT_INFO_CALL;
                        // p_disp_buff[j] = last_color;
                    }
                    same_color_cnt = (p_user_image[image_data_index] & 0x7F) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]];
                    if (addr_out_flag == 0)
                    {
                        DISP_POINT_INFO_CALL;
                        // p_disp_buff[j] = last_color;
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
    else
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] == 0xFF)
            {
                image_data_index++;
                same_color_cnt = (p_user_image[image_data_index]);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            addr_out_flag = 0;
            for (uint16_t j = 0; j < width; j++)
            {
                if (((j + x) < 0) || ((j + x) >= OLED_SIZE_X)) //地址溢出的不处理
                {
                    addr_out_flag |= 2;
                }
                else
                {
                    addr_out_flag &= ~2;
                }
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    if (addr_out_flag == 0)
                    {
                        DISP_POINT_INFO_CALL;
                        // p_disp_buff[j] = last_color;
                    }
                    continue;
                }

                if (p_user_image[image_data_index] == 0xFF)
                {
                    if (addr_out_flag == 0)
                    {
                        DISP_POINT_INFO_CALL;
                        // p_disp_buff[j] = last_color;
                    }
                    image_data_index++;
                    same_color_cnt = (p_user_image[image_data_index]) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]];
                    if (addr_out_flag == 0)
                    {
                        DISP_POINT_INFO_CALL;
                        // p_disp_buff[j] = last_color;
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
}
typedef struct __draw_over_y_t
{
    int y_base;
} draw_over_y_t;
void draw_point_callback_over_y(point_info_t const *point_info_t)
{
    int y_base = ((draw_over_y_t *)(point_info_t->draw_ext_para))->y_base;
    if (point_info_t->y >= y_base)
    {
        if (point_info_t->color != RGB565_COLOR_BLACK)
        {
            *point_info_t->point = point_info_t->color;
            //*point_info_t->point = get_filter_color(point_info_t->color, *point_info_t->point);
        }
    }
}
void disp_draw_user_image_over_y(int16_t x, int16_t y, const uint8_t *p_user_image, int y_base)
{
    draw_over_y_t const over_y_para = {
        .y_base = y_base,
    };
    disp_draw_user_image_ext(x, y, p_user_image, draw_point_callback_over_y, &over_y_para);
}
typedef struct __draw_less_x_t
{
    int x_base;
} draw_less_x_t;
void draw_point_callback_less_x(point_info_t const *point_info_t)
{
    int x_base = ((draw_less_x_t *)(point_info_t->draw_ext_para))->x_base;
    if (point_info_t->x <= x_base)
    {
        if (point_info_t->color != RGB565_COLOR_BLACK)
        {
            *point_info_t->point = point_info_t->color;
        }
    }
}
void disp_draw_user_image_less_x(int16_t x, int16_t y, const uint8_t *p_user_image, int x_base)
{
    draw_less_x_t const less_para = {
        .x_base = x_base,
    };
    disp_draw_user_image_ext(x, y, p_user_image, draw_point_callback_less_x, &less_para);
}

typedef struct __draw_transparent_t
{
    int color;
} draw_ltransparent_t;
void draw_point_callback_transparent(point_info_t const *point_info_t)
{
    int color = ((draw_ltransparent_t *)(point_info_t->draw_ext_para))->color;
    if (point_info_t->color != RGB565_COLOR_BLACK)
    {
        *point_info_t->point = get_multiply_color(point_info_t->color, color);
    }
}

void disp_draw_user_image_transparent(int16_t x, int16_t y, uint16_t color, const unsigned char *p_user_image)
{
    draw_ltransparent_t const para = {
        .color = color,
    };
    disp_draw_user_image_ext(x, y, p_user_image, draw_point_callback_transparent, &para);
}
void draw_point_callback_multiply(point_info_t const *point_info_t)
{
    *point_info_t->point = get_multiply_color(point_info_t->color, *point_info_t->point);
}
void disp_draw_user_image_multiply(int16_t x, int16_t y, const unsigned char *p_user_image)
{
    disp_draw_user_image_ext(x, y, p_user_image, draw_point_callback_multiply, 0);
}
typedef struct __draw_transparent_less_x_t
{
    int x_base;
    uint16_t color;
} draw_transparent_less_x_t;
void draw_point_callback_transparent_less_x(point_info_t const *point_info_t)
{
    int x_base = ((draw_transparent_less_x_t *)(point_info_t->draw_ext_para))->x_base;
    uint16_t color = ((draw_transparent_less_x_t *)(point_info_t->draw_ext_para))->color;
    if (point_info_t->x <= x_base)
    {
        if (point_info_t->color != RGB565_COLOR_BLACK)
        {
            *point_info_t->point = get_multiply_color(point_info_t->color, color);
        }
    }
}
void disp_draw_user_image_transparent_less_x(int16_t x, int16_t y, uint16_t color, const uint8_t *p_user_image, int x_base)
{
    draw_transparent_less_x_t const less_para = {
        .x_base = x_base,
        .color = color,
    };
    disp_draw_user_image_ext(x, y, p_user_image, draw_point_callback_transparent_less_x, &less_para);
}

typedef struct __draw_percent_circle_t
{
    int percent;
    int center_x;
    int center_y;
    int target_y;
    int target_inner_y;
    int target_x;
    int target_inner_x;
} draw_percent_circle_t;
static bool draw_point_callback_percent_circle_check(int x, int y, draw_percent_circle_t const *para)
{
    int const percent = para->percent;
    int const center_x = para->center_x;
    int const center_y = para->center_y;
    int const target_y = para->target_y;
    int const target_inner_y = para->target_inner_y;
    int const target_x = para->target_x;
    int const target_inner_x = para->target_inner_x;
    if (percent == 0)
    {
        return false;
    }
    else if (percent <= 25)
    {
        if (x <= center_x)
        {
            return false;
        }
        if (y > center_y)
        {
            return false;
        }
        if (x <= target_x && y <= target_y)
        {
            return true;
        }
    }
    else if (percent <= 50)
    {
        if (x <= center_x)
        {
            return false;
        }
        if (y <= center_y)
        {
            return true;
        }
        if (percent < 25 + 13)
        {
            if (x >= target_inner_x && y <= target_y)
            {
                return true;
            }
        }
        else
        {
            if (x >= target_inner_x)
            {
                return true;
            }
        }
    }
    else if (percent <= 75)
    {
        if (x >= center_x)
        {
            return true;
        }
        if (y < center_y)
        {
            return false;
        }
        if (percent < 50 + 13)
        {
            if (x >= target_x && y >= target_inner_y)
            {
                return true;
            }
        }
        else
        {
            if (y >= target_inner_y)
            {
                return true;
            }
        }
    }
    else if (percent < 100)
    {
        if (x >= center_x)
        {
            return true;
        }
        if (y >= center_y)
        {
            return true;
        }
        if (percent < 75 + 13)
        {
            if (x <= target_inner_x && y >= target_y)
            {
                return true;
            }
        }
        else
        {
            if (x <= target_inner_x)
            {
                return true;
            }
        }
    }
    else
    {
        return true;
    }
    return false;
}
static void draw_point_callback_percent_circle(point_info_t const *point_info_t)
{
    draw_percent_circle_t const *draw_percent_circle_para = (draw_percent_circle_t const *)(point_info_t->draw_ext_para);

    if (draw_point_callback_percent_circle_check(point_info_t->x, point_info_t->y, draw_percent_circle_para))
    {
        if (point_info_t->color != RGB565_COLOR_BLACK)
        {
            *point_info_t->point = point_info_t->color;
        }
    }
}
void disp_draw_user_image_percent_circle(int x, int y, uint8_t const *p_user_image, int percent, int inner_diameter)
{
    if (percent > 100)
    {
        percent = 100;
    }
    else if (percent < 0)
    {
        percent = 0;
    }
    int width = p_user_image[0] + (p_user_image[1] << 8);
    int height = p_user_image[2] + (p_user_image[3] << 8);
    float degree = percent * 2 * PI / 100;
    int target_y = height / 2 * cosf(degree);
    int target_x = height / 2 * sinf(degree);
    int target_inner_y = inner_diameter / 2 * cosf(degree);
    int target_inner_x = inner_diameter / 2 * sinf(degree);
    int center_x = x + width / 2;
    int center_y = y + height / 2;
    if (percent <= 25)
    {
        target_y = center_y - abs(target_y);
        target_inner_y = center_y - abs(target_inner_y);
        target_x = center_x + abs(target_x);
        target_inner_x = center_x + abs(target_inner_x);
    }
    else if (percent <= 50)
    {
        target_y = center_y + abs(target_y);
        target_inner_y = center_y + abs(target_inner_y);
        target_x = center_x + abs(target_x);
        target_inner_x = center_x + abs(target_inner_x);
    }
    else if (percent <= 75)
    {
        target_y = center_y + abs(target_y);
        target_inner_y = center_y + abs(target_inner_y);
        target_x = center_x - abs(target_x);
        target_inner_x = center_x - abs(target_inner_x);
    }
    else
    {
        target_y = center_y - abs(target_y);
        target_inner_y = center_y - abs(target_inner_y);
        target_x = center_x - abs(target_x);
        target_inner_x = center_x - abs(target_inner_x);
    }
    draw_percent_circle_t const draw_percent_circle_para = {
        .percent = percent,
        .center_x = center_x,
        .center_y = center_y,
        .target_y = target_y,
        .target_inner_y = target_inner_y,
        .target_x = target_x,
        .target_inner_x = target_inner_x,
    };
    disp_draw_user_image_ext(x, y, p_user_image, draw_point_callback_percent_circle, &draw_percent_circle_para);
}
/*********************************************************************************************
 * @brief 画自定义图片格式
 * @param [in] param1
 * @param [out] param2
 * @return ret
 * @note
 * @warning
 ********************************************************************************************/
void disp_draw_user_image(int16_t x, int16_t y, const uint8_t *p_user_image)
{
    /*图片格式
    uint16_t  width;
    uint16_t  height;
    uint16_t  color_tab_size;       //最大254
    uint16_t  color_tab[];              //颜色表
    uint8_t    color_index[];           //颜色数据的序号，最高位为1时代表有n个与前面一个相同颜色的点（不包含前面那个颜色）
    */
    uint16_t width, height;
    uint16_t color_number;
    uint16_t *color_tab = (uint16_t *)(p_user_image + 6);
    width = p_user_image[0] + (p_user_image[1] << 8);
    height = p_user_image[2] + (p_user_image[3] << 8);
    color_number = p_user_image[4] + (p_user_image[5] << 8);
    p_user_image += color_number * 2 + 6; //指向数据

    uint16_t last_color = color_tab[0];
    uint16_t same_color_cnt = 0;
    uint16_t image_data_index = 0;
    uint8_t addr_out_flag;

    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y + height - 1)) || (disp_ctrl.area_end_y < y))
    {
        return;
    }

    uint16_t *p_disp_buff;
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y - disp_ctrl.area_start_y) * OLED_SIZE_X + x; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + x; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y;
    }
    if (disp_ctrl.area_end_y >= (y + height - 1))
    {
        icon_end_y = height - 1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y;
    }

    //依次填充数据
    if (color_number <= 127)
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] & 0x80)
            {
                same_color_cnt = (p_user_image[image_data_index] & 0x7F);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            addr_out_flag = 0;
            for (uint16_t j = 0; j < width; j++)
            {
                if (((j + x) < 0) || ((j + x) >= OLED_SIZE_X)) //地址溢出的不处理
                {
                    addr_out_flag |= 2;
                }
                else
                {
                    addr_out_flag &= ~2;
                }
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = last_color;
                    }
                    continue;
                }

                if (p_user_image[image_data_index] & 0x80)
                {
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = last_color;
                    }
                    same_color_cnt = (p_user_image[image_data_index] & 0x7F) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]];
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = last_color;
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
    else
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] == 0xFF)
            {
                image_data_index++;
                same_color_cnt = (p_user_image[image_data_index]);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            addr_out_flag = 0;
            for (uint16_t j = 0; j < width; j++)
            {
                if (((j + x) < 0) || ((j + x) >= OLED_SIZE_X)) //地址溢出的不处理
                {
                    addr_out_flag |= 2;
                }
                else
                {
                    addr_out_flag &= ~2;
                }
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = last_color;
                    }
                    continue;
                }

                if (p_user_image[image_data_index] == 0xFF)
                {
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = last_color;
                    }
                    image_data_index++;
                    same_color_cnt = (p_user_image[image_data_index]) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]];
                    if (addr_out_flag == 0)
                    {
                        p_disp_buff[j] = last_color;
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
}

/*********************************************************************************************
 * @brief 画自定义图片格式
 * @param [in] param1
 * @param [out] param2
 * @return ret
 * @note
 * @warning
 ********************************************************************************************/
void disp_draw_user_image_ignore_color(int16_t x, int16_t y, uint16_t ignore_color, const uint8_t *p_user_image)
{
#if 0
#define DISP_DRAW_USER_IMAGE_IGNORE_COLOR_SET (get_color_mixture2(p_disp_buff[j], last_color))
#else
#define DISP_DRAW_USER_IMAGE_IGNORE_COLOR_SET last_color //(get_color_mixture2(p_disp_buff[j],last_color))
#endif
    /*图片格式
    uint16_t  width;
    uint16_t  height;
    uint16_t  color_tab_size;       //最大254
    uint16_t  color_tab[];              //颜色表
    uint8_t    color_index[];           //颜色数据的序号，最高位为1时代表有n个与前面一个相同颜色的点（不包含前面那个颜色）
    */
    uint16_t width, height;
    uint16_t color_number;
    uint16_t *color_tab = (uint16_t *)(p_user_image + 6);
    width = p_user_image[0] + (p_user_image[1] << 8);
    height = p_user_image[2] + (p_user_image[3] << 8);
    color_number = p_user_image[4] + (p_user_image[5] << 8);
    p_user_image += color_number * 2 + 6; //指向数据

    uint16_t last_color = color_tab[0];
    uint16_t same_color_cnt = 0;
    uint16_t image_data_index = 0;

    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y + height - 1)) || (disp_ctrl.area_end_y < y))
    {
        return;
    }

    uint16_t *p_disp_buff;
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y - disp_ctrl.area_start_y) * OLED_SIZE_X + x; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + x; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y;
    }
    if (disp_ctrl.area_end_y >= (y + height - 1))
    {
        icon_end_y = height - 1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y;
    }

    //依次填充数据
    if (color_number <= 127)
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] & 0x80)
            {
                same_color_cnt = (p_user_image[image_data_index] & 0x7F);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            for (uint16_t j = 0; j < width; j++)
            {
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    if (ignore_color != last_color)
                    {
                        p_disp_buff[j] = DISP_DRAW_USER_IMAGE_IGNORE_COLOR_SET;
                    }
                    continue;
                }

                if (p_user_image[image_data_index] & 0x80)
                {
                    if (ignore_color != last_color)
                    {
                        p_disp_buff[j] = DISP_DRAW_USER_IMAGE_IGNORE_COLOR_SET;
                    }
                    same_color_cnt = (p_user_image[image_data_index] & 0x7F) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]];
                    if (ignore_color != last_color)
                    {
                        p_disp_buff[j] = DISP_DRAW_USER_IMAGE_IGNORE_COLOR_SET;
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
}
/*********************************************************************************************
 * @brief 画自定义图片格式
 * @param [in] param1
 * @param [out] param2
 * @return ret
 * @note
 * @warning
 ********************************************************************************************/
void disp_draw_user_image_bg_color(int16_t x, int16_t y, uint16_t target_color, const uint8_t *p_user_image)
{
    /*图片格式
    uint16_t  width;
    uint16_t  height;
    uint16_t  color_tab_size;       //最大254
    uint16_t  color_tab[];              //颜色表
    uint8_t    color_index[];           //颜色数据的序号，最高位为1时代表有n个与前面一个相同颜色的点（不包含前面那个颜色）
    */
    uint16_t width, height;
    uint16_t color_number;
    uint16_t *color_tab = (uint16_t *)(p_user_image + 6);
    width = p_user_image[0] + (p_user_image[1] << 8);
    height = p_user_image[2] + (p_user_image[3] << 8);
    color_number = p_user_image[4] + (p_user_image[5] << 8);
    p_user_image += color_number * 2 + 6; //指向数据

    uint16_t last_color = color_tab[0];
    uint16_t same_color_cnt = 0;
    uint16_t image_data_index = 0;

    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y + height - 1)) || (disp_ctrl.area_end_y < y))
    {
        return;
    }

    uint16_t *p_disp_buff;
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y - disp_ctrl.area_start_y) * OLED_SIZE_X + x; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + x; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y;
    }
    if (disp_ctrl.area_end_y >= (y + height - 1))
    {
        icon_end_y = height - 1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y;
    }

    //依次填充数据
    if (color_number <= 127)
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] & 0x80)
            {
                same_color_cnt = (p_user_image[image_data_index] & 0x7F);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            for (uint16_t j = 0; j < width; j++)
            {
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    if ((p_disp_buff[j] == target_color) && (last_color != 0))
                    {
                        p_disp_buff[j] = last_color;
                    }
                    continue;
                }

                if (p_user_image[image_data_index] & 0x80)
                {
                    if ((p_disp_buff[j] == target_color) && (last_color != 0))
                    {
                        p_disp_buff[j] = last_color;
                    }
                    same_color_cnt = (p_user_image[image_data_index] & 0x7F) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]];
                    if ((p_disp_buff[j] == target_color) && (last_color != 0))
                    {
                        p_disp_buff[j] = last_color;
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
}
int disp_draw_user_image_num_mid_ignore_with_digit(int16_t x, int16_t y, uint16_t ignore_color, uint32_t num, uint8_t width, uint8_t digit, const unsigned char *const IMAGE_USER_NUM_TAB[])
{
    if ((x < (digit * width) / 2) || ((digit * width / 2 + x) > OLED_SIZE_X))
    {
        return 0; //溢出判断
    }
    x = x + (digit - 1) * width / 2 - (width + 1) / 2; //最后一个数字起始位置
    int const end_x = x + width;
    //依次 从最低位->最高位显示
    while (digit-- != 0)
    {
        disp_draw_user_image_ignore_color(x, y, ignore_color, IMAGE_USER_NUM_TAB[num % 10]);
        num /= 10;
        x -= width;
    }
    return end_x;
}
/*********************************************************************************************
 * @brief 居中显示数值
 * @param [in] param1
 * @warning 灰度+颜色叠加
 ********************************************************************************************/
int disp_draw_user_image_num_mid_ignore(int16_t x, int16_t y, uint16_t ignore_color, uint32_t num, uint8_t width, const unsigned char *const IMAGE_USER_NUM_TAB[])
{
    return disp_draw_user_image_num_mid_ignore_with_digit(x, y, ignore_color, num, width, get_num_digit(num), IMAGE_USER_NUM_TAB);
}

int disp_draw_user_image_num_right_align_filter_color(int16_t x, int16_t y, int32_t num, int interval, const unsigned char *const IMAGE_USER_NUM_TAB[])
{
    int const font_width = IMAGE_USER_NUM_TAB[0][0] + (IMAGE_USER_NUM_TAB[0][1] << 8);
    int const font_height = IMAGE_USER_NUM_TAB[0][2] + (IMAGE_USER_NUM_TAB[0][3] << 8);
    int digits = get_num_digit(num);
    int start_x = x - font_width * digits - interval * (digits - 1);
    int number = num;
    if (num < 0)
    {
        disp_draw_rect_color(start_x, y + font_height / 2 - 1, start_x + font_width - 1, y + font_height / 2, RGB565_COLOR_WHITE);
        digits--;
        number = -num;
    }

    int draw_number = 0;
    int draw_x = x - font_width;
    while (digits)
    {
        draw_number = number % 10;
        disp_draw_user_image_filter_color(draw_x, y, IMAGE_USER_NUM_TAB[draw_number]);
        draw_x -= interval + font_width;
        number /= 10;
        digits--;
    }
    return x;
}
int disp_draw_user_image_num_mid_filter_color(int16_t x, int16_t y, uint32_t num, uint8_t width, const unsigned char *const IMAGE_USER_NUM_TAB[])
{

    uint8_t temp8;
    uint32_t temp32;

    //计算起始显示位置
    temp32 = num;
    temp8 = 1;
    while (temp32 > 9)
    {
        temp8++; //代表输入数字的位数
        temp32 /= 10;
    }

    if ((x < (temp8 * width) / 2) || ((temp8 * width / 2 + x) > OLED_SIZE_X))
    {
        return 0; //溢出判断
    }
    x = x + (temp8 - 1) * width / 2 - (width + 1) / 2; //最后一个数字起始位置
    int const end_x = x + width;
    //依次 从最低位->最高位显示
    while (temp8-- != 0)
    {
        disp_draw_user_image_filter_color(x, y, IMAGE_USER_NUM_TAB[num % 10]);
        num /= 10;
        x -= width;
    }
    return end_x;
}
/*********************************************************************************************
 * @brief 画FLASH内的图片
 * @param [in] param1
 * @warning
 ********************************************************************************************/
void disp_draw_flash_image(uint16_t x, uint16_t y, uint16_t img_w, uint16_t img_h, lfs_file_t *p_file, int image_offset)
{
    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y + img_h - 1)) || (disp_ctrl.area_end_y < y))
    {
        return;
    }
    if (img_w == 0 && img_h == 0)
    {
        return;
    }
    //计算图片偏移
    uint16_t *p_disp_buff;            //指向显示的RAM
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y - disp_ctrl.area_start_y) * OLED_SIZE_X + x; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + x; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y;
    }
    if (disp_ctrl.area_end_y >= (y + img_h - 1))
    {
        icon_end_y = img_h - 1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y;
    }

    //文件的偏移位置和显示需要的坐标不一致时重新设置文件偏移
    if (p_file->pos != (img_w * icon_start_y * 2 + image_offset))
    {
        lfs_file_seek(&little_fs, p_file, img_w * icon_start_y * 2 + image_offset, 0);
    }

    int over_x = 0;

    if (img_w == OLED_SIZE_X) //满屏直接一次读到RAMbuff，否则需要分次读
    {
        lfs_file_read(&little_fs, p_file, p_disp_buff, (icon_end_y - icon_start_y + 1) * img_w * 2);
    }
    else
    {
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            over_x = x + img_w - 1 - OLED_SIZE_X;
            if (over_x > 0)
            {
                lfs_file_read(&little_fs, p_file, p_disp_buff, (img_w - over_x) * 2);
                lfs_file_seek(&little_fs, p_file, over_x * 2, LFS_SEEK_CUR);
            }
            else
            {
                lfs_file_read(&little_fs, p_file, p_disp_buff, img_w * 2);
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
}

/*********************************************************************************************
 * @brief 计算圆环参数
 * @param [in] degree 角度 0~359
 * @warning
 ********************************************************************************************/
void disp_annulus_calc(uint16_t degree, annulus_cfg_t *p_cfg)
{
    float angle = degree * PI / 180.f; //旋转角度
    float co = cos(angle);             //余弦
    float si = sin(angle);             //正弦
    if (degree == 0)
    {
        p_cfg->state = 0;
    }
    else if (degree >= 360)
    {
        p_cfg->state = 5;
    }
    else
    {
        p_cfg->state = ((degree - 1) / 90) + 1;
    }
    switch (p_cfg->state)
    {
    case 1:
        p_cfg->target_y1 = p_cfg->centre_y - co * p_cfg->r2;
        p_cfg->target_y2 = p_cfg->centre_y - co * p_cfg->r1;
        break;
    case 2:
        p_cfg->target_y1 = p_cfg->centre_y - co * p_cfg->r1;
        p_cfg->target_y2 = p_cfg->centre_y - co * p_cfg->r2;
        break;
    case 3:
        p_cfg->target_y1 = p_cfg->centre_y - co * p_cfg->r1;
        p_cfg->target_y2 = p_cfg->centre_y - co * p_cfg->r2;
        break;
    case 4:
        p_cfg->target_y1 = p_cfg->centre_y - co * p_cfg->r2;
        p_cfg->target_y2 = p_cfg->centre_y - co * p_cfg->r1;
        break;
    default:
        break;
    }
    p_cfg->cot_angle = co / si;
}

/*********************************************************************************************
 * @brief 根据输入的角度，画FLASH内的圆环图片
 * @param [in] degree 角度
 * @warning
 ********************************************************************************************/
void disp_draw_flash_image_annulus(int16_t x, int16_t y, uint16_t ignore_color, uint16_t img_w, uint16_t img_h, lfs_file_t *p_file, annulus_cfg_t *p_annulus_cfg)
{
    if (p_annulus_cfg->state == 0)
    {
        return;
    }
    // else if (p_annulus_cfg->state == 5)
    // {
    //     return;
    // }
    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y + img_h - 1)) || (disp_ctrl.area_end_y < y))
    {
        return;
    }
    //计算图片偏移
    uint16_t *p_disp_buff;            //指向显示的RAM
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y - disp_ctrl.area_start_y) * OLED_SIZE_X; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag]; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y;
    }
    if (disp_ctrl.area_end_y >= (y + img_h - 1))
    {
        icon_end_y = img_h - 1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y;
    }

    //文件的偏移位置和显示需要的坐标不一致时重新设置文件偏移
    if (p_file->off != (img_w * icon_start_y * 2 + 4))
    {
        lfs_file_seek(&little_fs, p_file, img_w * icon_start_y * 2 + 4, 0);
    }

    //判断
    uint16_t color_buff[OLED_SIZE_X];
    for (uint16_t i = icon_start_y + y; i <= (icon_end_y + y); i++)
    {
        switch (p_annulus_cfg->state)
        {
        case 1:
        case 2: //只有右半圆
            if (i > p_annulus_cfg->target_y2)
            {
                i = icon_end_y + y + 1; //结束循环
                break;
            }
            lfs_file_read(&little_fs, p_file, color_buff + x, img_w * 2);
            if ((i >= p_annulus_cfg->target_y1) && (i <= p_annulus_cfg->target_y2)) //在交叉区域需要计算角度
            {
                for (uint8_t j = p_annulus_cfg->centre_x; j < x + img_w; j++) //依次判断颜色值是否符合
                {
                    if (color_buff[j] != ignore_color) //符合
                    {
                        if (i <= (p_annulus_cfg->centre_y - (j - p_annulus_cfg->centre_x) * p_annulus_cfg->cot_angle))
                        {
                            p_disp_buff[j] = color_buff[j];
                        }
                    }
                }
            }
            else
            {
                for (uint8_t j = p_annulus_cfg->centre_x; j < x + img_w; j++) //依次判断颜色值是否符合
                {
                    if (color_buff[j] != ignore_color) //符合
                    {
                        p_disp_buff[j] = color_buff[j];
                    }
                }
            }
            break;
        case 3:
        case 4: //左部分+右边全部
        case 5:
            lfs_file_read(&little_fs, p_file, color_buff + x, img_w * 2);
            for (uint8_t j = x; j < p_annulus_cfg->centre_x; j++) //依次判断颜色值是否符合
            {
                if (color_buff[j] != ignore_color) //符合
                {
                    if ((p_annulus_cfg->state == 5) || (i >= (p_annulus_cfg->centre_y - (j - p_annulus_cfg->centre_x) * p_annulus_cfg->cot_angle)))
                    {
                        p_disp_buff[j] = color_buff[j];
                    }
                }
            }
            for (uint8_t j = p_annulus_cfg->centre_x; j < x + img_w; j++) //依次判断颜色值是否符合
            {
                if (color_buff[j] != ignore_color) //符合
                {
                    p_disp_buff[j] = color_buff[j];
                }
            }
            break;

        default:
            break;
        }

        p_disp_buff += OLED_SIZE_X;
    }
}
/*********************************************************************************************
 * @brief 颜色透明混合，只支持灰度图
 * @param [in] gray_level 0~31
 * @warning
 ********************************************************************************************/
static uint16_t get_color_by_gray_level(uint16_t color, uint8_t gray_level)
{
    uint8_t red, green, blue;

    blue = ((color & 0x1F) * gray_level) / 31;
    green = (((color >> 5) & 0x3F) * gray_level) / 31;
    red = (((color >> 11) & 0x1F) * gray_level) / 31;

    return (red << 11) | (green << 5) | (blue);
}
/*********************************************************************************************
 * @brief 画自定义的灰度图，有底色时透明处理
 * @param [in] param1
 * @param [out] param2
 * @warning
 ********************************************************************************************/
void disp_draw_user_image_lucency_ignore(int16_t x, int16_t y, uint16_t ignore_color, const unsigned char *p_user_image)
{

    /*图片格式
    uint16_t  width;
    uint16_t  height;
    uint16_t  color_tab_size;       //最大254
    uint16_t  color_tab[];              //颜色表
    uint8_t    color_index[];           //颜色数据的序号，最高位为1时代表有n个与前面一个相同颜色的点（不包含前面那个颜色）
    */
    uint16_t width, height;
    uint16_t color_number;
    uint16_t *color_tab = (uint16_t *)(p_user_image + 6);
    width = p_user_image[0] + (p_user_image[1] << 8);
    height = p_user_image[2] + (p_user_image[3] << 8);
    color_number = p_user_image[4] + (p_user_image[5] << 8);
    p_user_image += color_number * 2 + 6; //指向数据

    uint16_t last_color = color_tab[0];
    uint16_t same_color_cnt = 0;
    uint16_t image_data_index = 0;

    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y + height - 1)) || (disp_ctrl.area_end_y < y))
    {
        return;
    }

    uint16_t *p_disp_buff;
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y - disp_ctrl.area_start_y) * OLED_SIZE_X + x; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + x; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y;
    }
    if (disp_ctrl.area_end_y >= (y + height - 1))
    {
        icon_end_y = height - 1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y;
    }

    //依次填充数据
    if (color_number <= 127)
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] & 0x80)
            {
                same_color_cnt = (p_user_image[image_data_index] & 0x7F);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            for (uint16_t j = 0; j < width; j++)
            {
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    if (ignore_color != last_color)
                    {
                        p_disp_buff[j] = get_color_mixture(last_color, p_disp_buff[j]);
                    }
                    continue;
                }

                if (p_user_image[image_data_index] & 0x80)
                {
                    if (last_color != ignore_color)
                    {
                        p_disp_buff[j] = get_color_mixture(last_color, p_disp_buff[j]);
                    }
                    same_color_cnt = (p_user_image[image_data_index] & 0x7F) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]];
                    if (last_color != ignore_color)
                    {
                        p_disp_buff[j] = get_color_mixture(last_color, p_disp_buff[j]);
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
    else
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] == 0xFF)
            {
                image_data_index++;
                same_color_cnt = (p_user_image[image_data_index]);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            for (uint16_t j = 0; j < width; j++)
            {

                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    if (last_color != ignore_color)
                    {
                        p_disp_buff[j] = last_color;
                    }
                    continue;
                }

                if (p_user_image[image_data_index] == 0xFF)
                {
                    if (last_color != ignore_color)
                    {
                        p_disp_buff[j] = get_color_mixture(last_color, p_disp_buff[j]);
                    }
                    image_data_index++;
                    same_color_cnt = (p_user_image[image_data_index]) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]];
                    if (last_color != ignore_color)
                    {
                        p_disp_buff[j] = get_color_mixture(last_color, p_disp_buff[j]);
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
}
/*********************************************************************************************
 * @brief 画自定义图，有底色时半透明处理
 * @param [in] param1
 * @param [out] param2
 * @warning
 ********************************************************************************************/
void disp_draw_user_image_half_lucency_ignore(int16_t x, int16_t y, uint16_t ignore_color, const unsigned char *p_user_image)
{

    /*图片格式
    uint16_t  width;
    uint16_t  height;
    uint16_t  color_tab_size;       //最大254
    uint16_t  color_tab[];              //颜色表
    uint8_t    color_index[];           //颜色数据的序号，最高位为1时代表有n个与前面一个相同颜色的点（不包含前面那个颜色）
    */
    uint16_t width, height;
    uint16_t color_number;
    uint16_t *color_tab = (uint16_t *)(p_user_image + 6);
    width = p_user_image[0] + (p_user_image[1] << 8);
    height = p_user_image[2] + (p_user_image[3] << 8);
    color_number = p_user_image[4] + (p_user_image[5] << 8);
    p_user_image += color_number * 2 + 6; //指向数据

    uint16_t last_color = color_tab[0];
    uint16_t same_color_cnt = 0;
    uint16_t image_data_index = 0;

    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y + height - 1)) || (disp_ctrl.area_end_y < y))
    {
        return;
    }

    uint16_t *p_disp_buff;
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y - disp_ctrl.area_start_y) * OLED_SIZE_X + x; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + x; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y;
    }
    if (disp_ctrl.area_end_y >= (y + height - 1))
    {
        icon_end_y = height - 1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y;
    }

    //依次填充数据
    if (color_number <= 127)
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] & 0x80)
            {
                same_color_cnt = (p_user_image[image_data_index] & 0x7F);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            for (uint16_t j = 0; j < width; j++)
            {
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    if (ignore_color != last_color)
                    {
                        p_disp_buff[j] = get_color_mixture2(last_color, p_disp_buff[j]);
                    }
                    continue;
                }

                if (p_user_image[image_data_index] & 0x80)
                {
                    if (last_color != ignore_color)
                    {
                        p_disp_buff[j] = get_color_mixture2(last_color, p_disp_buff[j]);
                    }
                    same_color_cnt = (p_user_image[image_data_index] & 0x7F) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]];
                    if (last_color != ignore_color)
                    {
                        p_disp_buff[j] = get_color_mixture2(last_color, p_disp_buff[j]);
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
}
/*********************************************************************************************
 * @brief 居中显示数值
 * @param [in] param1
 * @warning 灰度+颜色叠加
 ********************************************************************************************/
void disp_draw_user_image_num_mid_gray_lucency_ignore(int16_t x, int16_t y, uint16_t ignore_color, uint32_t num, uint8_t width, const unsigned char *const IMAGE_USER_NUM_TAB[])
{
    uint8_t temp8;
    uint32_t temp32;

    //计算起始显示位置
    temp32 = num;
    temp8 = 1;
    while (temp32 > 9)
    {
        temp8++; //代表输入数字的位数
        temp32 /= 10;
    }

    if ((x < (temp8 * width) / 2) || ((temp8 * width / 2 + x) > OLED_SIZE_X))
    {
        return; //溢出判断
    }
    x = x + (temp8 - 1) * width / 2 - (width + 1) / 2; //最后一个数字起始位置

    //依次 从最低位->最高位显示
    while (temp8-- != 0)
    {
        disp_draw_user_image_lucency_ignore(x, y, ignore_color, IMAGE_USER_NUM_TAB[num % 10]);
        num /= 10;
        x -= width;
    }
}
/*********************************************************************************************
 * @brief 画自定义的灰度图，有底色时透明处理
 * @param [in] param1
 * @param [out] param2
 * @warning
 ********************************************************************************************/
void disp_draw_user_image_gray_lucency(int16_t x, int16_t y, uint16_t color, const unsigned char *p_user_image)
{

    /*图片格式
    uint16_t  width;
    uint16_t  height;
    uint16_t  color_tab_size;       //最大254
    uint16_t  color_tab[];              //颜色表
    uint8_t    color_index[];           //颜色数据的序号，最高位为1时代表有n个与前面一个相同颜色的点（不包含前面那个颜色）
    */
    uint16_t width, height;
    uint16_t color_number;
    uint16_t *color_tab = (uint16_t *)(p_user_image + 6);
    width = p_user_image[0] + (p_user_image[1] << 8);
    height = p_user_image[2] + (p_user_image[3] << 8);
    color_number = p_user_image[4] + (p_user_image[5] << 8);
    p_user_image += color_number * 2 + 6; //指向数据

    uint16_t last_color = color_tab[0];
    uint16_t same_color_cnt = 0;
    uint16_t image_data_index = 0;

    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y + height - 1)) || (disp_ctrl.area_end_y < y))
    {
        return;
    }

    uint16_t *p_disp_buff;
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y - disp_ctrl.area_start_y) * OLED_SIZE_X + x; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + x; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y;
    }
    if (disp_ctrl.area_end_y >= (y + height - 1))
    {
        icon_end_y = height - 1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y;
    }

    //依次填充数据
    if (color_number <= 127)
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] & 0x80)
            {
                same_color_cnt = (p_user_image[image_data_index] & 0x7F);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            for (uint16_t j = 0; j < width; j++)
            {
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    {
                        p_disp_buff[j] = get_color_mixture3(last_color, p_disp_buff[j]);
                    }
                    continue;
                }

                if (p_user_image[image_data_index] & 0x80)
                {
                    {
                        p_disp_buff[j] = get_color_mixture3(last_color, p_disp_buff[j]);
                    }
                    same_color_cnt = (p_user_image[image_data_index] & 0x7F) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]] & 0x1F; //灰度颜色
                    last_color = get_color_by_gray_level(color, last_color);       //灰度颜色转要填充的颜色
                    {
                        p_disp_buff[j] = get_color_mixture3(last_color, p_disp_buff[j]);
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
    else
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] == 0xFF)
            {
                image_data_index++;
                same_color_cnt = (p_user_image[image_data_index]);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            for (uint16_t j = 0; j < width; j++)
            {
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    {
                        p_disp_buff[j] = last_color;
                    }
                    continue;
                }

                if (p_user_image[image_data_index] == 0xFF)
                {
                    {
                        p_disp_buff[j] = get_color_mixture3(last_color, p_disp_buff[j]);
                    }
                    image_data_index++;
                    same_color_cnt = (p_user_image[image_data_index]) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]] & 0x1F; //灰度颜色
                    last_color = get_color_by_gray_level(color, last_color);       //灰度颜色转要填充的颜色
                    {
                        p_disp_buff[j] = get_color_mixture3(last_color, p_disp_buff[j]);
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
}
/*********************************************************************************************
 * @brief 画自定义的灰度图，有底色时透明处理
 * @param [in] param1
 * @param [out] param2
 * @warning
 ********************************************************************************************/
void disp_draw_user_image_gray(int16_t x, int16_t y, uint16_t color, const unsigned char *p_user_image)
{

    /*图片格式
    uint16_t  width;
    uint16_t  height;
    uint16_t  color_tab_size;       //最大254
    uint16_t  color_tab[];              //颜色表
    uint8_t    color_index[];           //颜色数据的序号，最高位为1时代表有n个与前面一个相同颜色的点（不包含前面那个颜色）
    */
    uint16_t width, height;
    uint16_t color_number;
    uint16_t *color_tab = (uint16_t *)(p_user_image + 6);
    width = p_user_image[0] + (p_user_image[1] << 8);
    height = p_user_image[2] + (p_user_image[3] << 8);
    color_number = p_user_image[4] + (p_user_image[5] << 8);
    p_user_image += color_number * 2 + 6; //指向数据

    uint16_t last_color = color_tab[0];
    uint16_t same_color_cnt = 0;
    uint16_t image_data_index = 0;

    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y + height - 1)) || (disp_ctrl.area_end_y < y))
    {
        return;
    }

    uint16_t *p_disp_buff;
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y - disp_ctrl.area_start_y) * OLED_SIZE_X + x; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + x; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y;
    }
    if (disp_ctrl.area_end_y >= (y + height - 1))
    {
        icon_end_y = height - 1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y;
    }

    //依次填充数据
    if (color_number <= 127)
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] & 0x80)
            {
                same_color_cnt = (p_user_image[image_data_index] & 0x7F);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
                last_color = get_color_by_gray_level(color, last_color); //灰度颜色转要填充的颜色
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            for (uint16_t j = 0; j < width; j++)
            {
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    if (0 != last_color)
                    {
                        p_disp_buff[j] = last_color;
                    }
                    continue;
                }

                if (p_user_image[image_data_index] & 0x80)
                {
                    if (0 != last_color)
                    {
                        p_disp_buff[j] = last_color;
                    }
                    same_color_cnt = (p_user_image[image_data_index] & 0x7F) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]] & 0x1F; //灰度颜色
                    last_color = get_color_by_gray_level(color, last_color);       //灰度颜色转要填充的颜色
                    if (0 != last_color)
                    {
                        p_disp_buff[j] = last_color;
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
    else
    {
        //计算跳过的数据
        uint16_t invalid_cnt = icon_start_y * width;
        uint8_t same_color_cnt_flag = 0;
        while (invalid_cnt > 0)
        {
            if (p_user_image[image_data_index] == 0xFF)
            {
                image_data_index++;
                same_color_cnt = (p_user_image[image_data_index]);
                if (invalid_cnt >= same_color_cnt)
                {
                    invalid_cnt -= same_color_cnt;
                }
                else
                {
                    same_color_cnt -= invalid_cnt;
                    invalid_cnt = 0;
                    same_color_cnt_flag = 1;
                }
            }
            else
            {
                invalid_cnt--;
                last_color = color_tab[p_user_image[image_data_index]];
                last_color = get_color_by_gray_level(color, last_color); //灰度颜色转要填充的颜色
            }
            image_data_index++;
        }
        if (same_color_cnt_flag == 0)
        {
            same_color_cnt = 0;
        }
        for (uint16_t i = icon_start_y; i <= icon_end_y; i++)
        {
            for (uint16_t j = 0; j < width; j++)
            {
                if (same_color_cnt) //继续相同颜色的填充
                {
                    same_color_cnt--;
                    if (0 != last_color)
                    {
                        p_disp_buff[j] = last_color;
                    }
                    continue;
                }

                if (p_user_image[image_data_index] == 0xFF)
                {
                    if (0 != last_color)
                    {
                        p_disp_buff[j] = last_color;
                    }
                    image_data_index++;
                    same_color_cnt = (p_user_image[image_data_index]) - 1;
                }
                else
                {
                    last_color = color_tab[p_user_image[image_data_index]] & 0x1F; //灰度颜色
                    last_color = get_color_by_gray_level(color, last_color);       //灰度颜色转要填充的颜色
                    if (0 != last_color)
                    {
                        p_disp_buff[j] = last_color;
                    }
                }
                image_data_index++;
            }
            p_disp_buff += OLED_SIZE_X;
        }
    }
}
/*********************************************************************************************
 * @brief 居中显示数值
 * @param [in] param1
 * @warning 灰度+颜色叠加
 ********************************************************************************************/
void disp_draw_user_image_num_mid_gray_lucency(int16_t x, int16_t y, uint16_t color, uint32_t num, uint8_t width, const unsigned char *const IMAGE_USER_NUM_TAB[])
{
    uint8_t temp8;
    uint32_t temp32;

    //计算起始显示位置
    temp32 = num;
    temp8 = 1;
    while (temp32 > 9)
    {
        temp8++; //代表输入数字的位数
        temp32 /= 10;
    }

    if ((x < (temp8 * width) / 2) || ((temp8 * width / 2 + x) > OLED_SIZE_X))
    {
        return; //溢出判断
    }
    x = x + (temp8 - 1) * width / 2 - (width + 1) / 2; //最后一个数字起始位置

    //依次 从最低位->最高位显示
    while (temp8-- != 0)
    {
        disp_draw_user_image_gray_lucency(x, y, color, IMAGE_USER_NUM_TAB[num % 10]);
        num /= 10;
        x -= width;
    }
}

/*********************************************************************************************
 * @brief 开方
 * @param [in] param1
 * @warning
 ********************************************************************************************/
unsigned int sqrt_16(unsigned long M)
{
    unsigned int N, i;
    unsigned long tmp, ttp; // 结果、循环计数
    if (M == 0)             // 被开方数，开方结果也为0
        return 0;
    N = 0;
    tmp = (M >> 30); // 获取最高位：B[m-1]
    M <<= 2;
    if (tmp > 1) // 最高位为1
    {
        N++; // 结果当前位为1，否则为默认的0
        tmp -= N;
    }
    for (i = 15; i > 0; i--) // 求剩余的15位
    {
        N <<= 1; // 左移一位
        tmp <<= 2;
        tmp += (M >> 30); // 假设
        ttp = N;
        ttp = (ttp << 1) + 1;
        M <<= 2;
        if (tmp >= ttp) // 假设成立
        {
            tmp -= ttp;
            N++;
        }
    }
    return N;
}

/*********************************************************************************************
 * @brief 左下角到右上角的渐变处理,线条方式
 * @warning
 ********************************************************************************************/
void disp_draw_image_gradual_lb_2_rt_line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t start_color, uint16_t end_color)
{
    float interval_r, interval_g, interval_b;

    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y1)) || (disp_ctrl.area_end_y < y2))
    {
        return;
    }

    uint16_t dist = x2 - x1 + y1 - y2;
    interval_r = (float)((end_color >> 11) - (start_color >> 11)) / dist;
    interval_g = (float)(((end_color >> 5) & 0x3f) - ((start_color >> 5) & 0x3f)) / dist;
    interval_b = (float)((end_color & 0x1f) - (start_color & 0x1f)) / dist;

    uint16_t *p_disp_buff;
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y2 >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y2 - disp_ctrl.area_start_y) * OLED_SIZE_X; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag]; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y2;
    }
    if (disp_ctrl.area_end_y >= (y1))
    {
        icon_end_y = y1 - y2;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y2;
    }
    int16_t base_xy = y1 - icon_start_y - y2;
    // COLOR = [base-(x-y)]*interval
    float base_color_r = RGB565_GET_COLOR_R(start_color) + base_xy * interval_r;
    float base_color_g = RGB565_GET_COLOR_G(start_color) + base_xy * interval_g;
    float base_color_b = RGB565_GET_COLOR_B(start_color) + base_xy * interval_b;

    for (uint8_t y = icon_start_y + y2; y <= (icon_end_y + y2); y++)
    {
        float adj_r = base_color_r, adj_g = base_color_g, adj_b = base_color_b;
        for (uint8_t x = x1; x <= x2; x++)
        {
            p_disp_buff[x] = ((uint8_t)adj_r << 11) | ((uint8_t)adj_g << 5) | ((uint8_t)adj_b);
            adj_r += interval_r;
            adj_g += interval_g;
            adj_b += interval_b;
        }
        p_disp_buff += OLED_SIZE_X;

        base_color_r -= interval_r;
        base_color_g -= interval_g;
        base_color_b -= interval_b;
    }
}

/*********************************************************************************************
 * @brief 左下角到右上角的渐变处理,线条方式
 * @warning
 ********************************************************************************************/
void disp_draw_image_gradual_change_lb_2_rt_line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t start_color, uint16_t end_color)
{
    float interval_r, interval_g, interval_b;

    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y1)) || (disp_ctrl.area_end_y < y2))
    {
        return;
    }

    uint16_t dist = x2 - x1 + y1 - y2;
    interval_r = (float)((end_color >> 11) - (start_color >> 11)) / dist;
    interval_g = (float)(((end_color >> 5) & 0x3f) - ((start_color >> 5) & 0x3f)) / dist;
    interval_b = (float)((end_color & 0x1f) - (start_color & 0x1f)) / dist;

    uint16_t *p_disp_buff;
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y2 >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y2 - disp_ctrl.area_start_y) * OLED_SIZE_X; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag]; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y2;
    }
    if (disp_ctrl.area_end_y >= (y1))
    {
        icon_end_y = y1 - y2;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y2;
    }
    int16_t base_xy = y1 - icon_start_y - y2;
    // COLOR = [base-(x-y)]*interval
    float base_color_r = RGB565_GET_COLOR_R(start_color) + base_xy * interval_r;
    float base_color_g = RGB565_GET_COLOR_G(start_color) + base_xy * interval_g;
    float base_color_b = RGB565_GET_COLOR_B(start_color) + base_xy * interval_b;

    for (uint8_t y = icon_start_y + y2; y <= (icon_end_y + y2); y++)
    {
        float adj_r = base_color_r, adj_g = base_color_g, adj_b = base_color_b;
        for (uint8_t x = x1; x <= x2; x++)
        {
            if (p_disp_buff[x] != 0)
            {
                uint16_t color_t = ((uint8_t)adj_r << 11) | ((uint8_t)adj_g << 5) | ((uint8_t)adj_b);
                p_disp_buff[x] = get_color_by_gray_level(color_t, p_disp_buff[x] & 0x1f); //灰度颜色转要填充的颜色;
            }

            adj_r += interval_r;
            adj_g += interval_g;
            adj_b += interval_b;
        }
        p_disp_buff += OLED_SIZE_X;

        base_color_r -= interval_r;
        base_color_g -= interval_g;
        base_color_b -= interval_b;
    }
}

/*********************************************************************************************
 * @brief 垂直方向渐变颜色
 * @param [in] x1,y1左上角坐标，x2,y2右下角坐标
 * @warning 由上至下
 ********************************************************************************************/
void disp_draw_image_gradual_change_t_2_b(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t start_color, uint16_t end_color, uint16_t ignore_color)
{
    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y2)) || (disp_ctrl.area_end_y < y1))
    {
        return;
    }

    float interval_r, interval_g, interval_b;
    uint8_t h = y2 - y1;
    interval_r = ((float)((end_color >> 11) - (start_color >> 11))) / h;
    interval_g = (float)(((end_color >> 5) & 0x3f) - ((start_color >> 5) & 0x3f)) / h;
    interval_b = (float)((end_color & 0x1f) - (start_color & 0x1f)) / h;
    uint16_t *p_disp_buff;
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y1 >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y1 - disp_ctrl.area_start_y) * OLED_SIZE_X; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag]; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y1;
    }
    if (disp_ctrl.area_end_y >= (y2))
    {
        icon_end_y = y2 - y1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y1;
    }

    uint8_t r, g, b;
    uint16_t max_color, max_color_type; //取颜色值中r,g,b占比最大的值用于透明度计算，合成透明颜色
    r = start_color >> 11;
    g = (start_color & 0x07E0) >> 6; // g有6bit,多右移一位和r,b保持一致
    b = start_color & 0x1f;
    if ((g > r) || (b > r))
    {
        if (g > b)
        {
            max_color_type = 0x07E0;
        }
        else
        {
            max_color_type = 0x001F;
        }
    }
    else
    {
        max_color_type = 0xF800;
    }
    max_color = start_color & max_color_type;
    for (uint8_t i = icon_start_y; i <= icon_end_y; i++) //从1开始，首行不改变
    {
        float adj_r, adj_g, adj_b;
        for (uint8_t x = x1; x <= x2; x++)
        {
            if ((p_disp_buff[x] != ignore_color)) //不为空即调整颜色--也可以改为=start_color调整，视需要的效果来定
            {
                if (p_disp_buff[x] != start_color)
                {
                    adj_r = (interval_r * i * (p_disp_buff[x] & max_color_type)) / max_color;
                    adj_g = (interval_g * i * (p_disp_buff[x] & max_color_type)) / max_color;
                    adj_b = (interval_b * i * (p_disp_buff[x] & max_color_type)) / max_color;
                }
                else
                {
                    adj_r = interval_r * i;
                    adj_g = interval_g * i;
                    adj_b = interval_b * i;
                }
                r = p_disp_buff[x] >> 11;
                g = (p_disp_buff[x] >> 5) & 0x3f;
                b = p_disp_buff[x] & 0x1f;
                r += (int8_t)adj_r;
                g += (int8_t)adj_g;
                b += (int8_t)adj_b;

                if ((r > 31))
                {
                    r = 31;
                }
                if (g > 63)
                {
                    g = 63;
                }
                if (b > 31)
                {
                    b = 31;
                }
                p_disp_buff[x] = (r << 11) | (g << 5) | (b);
            }
        }
        p_disp_buff += OLED_SIZE_X;
    }
}

/*********************************************************************************************
 * @brief 垂直方向渐变颜色
 * @param [in] x1,y1左上角坐标，x2,y2右下角坐标
 * @warning 由上至下
 ********************************************************************************************/
void disp_draw_image_gradual_fill_t_2_b(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t start_color, uint16_t end_color, uint16_t ignore_color)
{
    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y2)) || (disp_ctrl.area_end_y < y1))
    {
        return;
    }

    float interval_r, interval_g, interval_b;
    uint8_t h = y2 - y1;
    interval_r = ((float)((end_color >> 11) - (start_color >> 11))) / h;
    interval_g = (float)(((end_color >> 5) & 0x3f) - ((start_color >> 5) & 0x3f)) / h;
    interval_b = (float)((end_color & 0x1f) - (start_color & 0x1f)) / h;
    uint16_t *p_disp_buff;
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y1 >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y1 - disp_ctrl.area_start_y) * OLED_SIZE_X; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag]; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y1;
    }
    if (disp_ctrl.area_end_y >= (y2))
    {
        icon_end_y = y2 - y1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y1;
    }

    // COLOR = [base-(x-y)]*interval
    float base_color_r = RGB565_GET_COLOR_R(start_color) + icon_start_y * interval_r;
    float base_color_g = RGB565_GET_COLOR_G(start_color) + icon_start_y * interval_g;
    float base_color_b = RGB565_GET_COLOR_B(start_color) + icon_start_y * interval_b;

    for (uint8_t y = icon_start_y; y <= (icon_end_y); y++)
    {
        for (uint8_t x = x1; x <= x2; x++)
        {
            p_disp_buff[x] = ((uint8_t)base_color_r << 11) | ((uint8_t)base_color_g << 5) | ((uint8_t)base_color_b);
        }
        p_disp_buff += OLED_SIZE_X;
        base_color_r += interval_r;
        base_color_g += interval_g;
        base_color_b += interval_b;
    }
}
/*********************************************************************************************
 * @brief 填充矩形区域为固定颜色
 * @param [in] 左上角坐标+右下角坐标
 * @warning
 ********************************************************************************************/
void disp_draw_rect_color(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color)
{
    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y2)) || (disp_ctrl.area_end_y < y1))
    {
        return;
    }

    uint16_t *p_disp_buff;
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y1 >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y1 - disp_ctrl.area_start_y) * OLED_SIZE_X; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag]; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y1;
    }
    if (disp_ctrl.area_end_y >= (y2))
    {
        icon_end_y = y2 - y1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y1;
    }

    for (uint8_t i = icon_start_y; i <= icon_end_y; i++)
    {
        for (uint8_t j = x1; j <= x2; j++)
        {
            *(p_disp_buff + j) = color;
        }
        p_disp_buff += OLED_SIZE_X;
    }
}

/*********************************************************************************************
 * @brief 颜色透明混合
 * @param [in] alpha 0~256
 * @warning
 ********************************************************************************************/
static uint16_t get_color_alpha(uint16_t color, uint16_t alpha)
{
    uint16_t red, green, blue;

    blue = (RGB565_GET_COLOR_B(color) * alpha) >> 8;
    green = (RGB565_GET_COLOR_G(color) * alpha) >> 8;
    red = (RGB565_GET_COLOR_R(color) * alpha) >> 8;
    return (red << 11) | (green << 5) | (blue);
}
/*********************************************************************************************
 * @brief 填充矩形区域为固定颜色
 * @param [in] 左上角坐标+右下角坐标 alpha:0~256
 * @warning
 ********************************************************************************************/
void disp_draw_rect_color_mixture(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t alpha)
{
    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y2)) || (disp_ctrl.area_end_y < y1))
    {
        return;
    }

    uint16_t *p_disp_buff;
    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y1 >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y1 - disp_ctrl.area_start_y) * OLED_SIZE_X; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag]; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y1;
    }
    if (disp_ctrl.area_end_y >= (y2))
    {
        icon_end_y = y2 - y1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y1;
    }

    for (uint8_t i = icon_start_y; i <= icon_end_y; i++)
    {
        for (uint8_t j = x1; j <= x2; j++)
        {
            *(p_disp_buff + j) = get_color_alpha(*(p_disp_buff + j), alpha);
        }
        p_disp_buff += OLED_SIZE_X;
    }
}
void disp_draw_img_rotate_with_solid(const unsigned char *p_image, uint16_t ignore_color, uint32_t centre_xy, uint32_t centre_set_xy, uint16_t degree, int solid_colour, bool transparency_by_white)
{
    uint16_t *pSrc = (uint16_t *)(p_image + 4);
    int16_t img_w = p_image[1] << 8 | p_image[0];
    int16_t img_h = p_image[3] << 8 | p_image[2];

    int16_t x0 = img_w / 2; //默认x轴在中点
    int16_t y0 = centre_xy & 0xFFFF;

    float angle = degree * PI / 180.f; //旋转角度
    float co = cos(angle);             //余弦
    float si = sin(angle);             //正弦
    int rotateW, rotateH;              //旋转后图像的高宽

    int xMin, xMax, yMin, yMax;
    int xOff, yOff; //偏移
    float xSrc = 0.;
    float ySrc = 0.; //变换后图像的坐标在原图中的坐标

    //临时变量
    uint16_t a1, a2, a3, a4;

    //计算旋转后的坐标范围
    rotateH = img_w * fabs(si) + img_h * fabs(co);
    rotateW = img_w * fabs(co) + img_h * fabs(si);

    //计算偏移
    xOff = (centre_set_xy >> 16) - x0;
    yOff = (centre_set_xy & 0xFFFF) - y0;
    yMin = y0 - (y0 - img_h / 2) * co - rotateH / 2;
    yMax = yMin + rotateH + 1; //加1

    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (yMax + yOff)) || (disp_ctrl.area_end_y < yMin + yOff))
    {
        return;
    }

    xMin = x0 + (y0 - img_h / 2) * si - rotateW / 2; //  (y0*si + (img_w-x0)*co-rotateW);
    xMax = xMin + rotateW + 1;

    uint16_t *p_disp_buff;
    if ((yMin + yOff) >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + ((yMin + yOff) - disp_ctrl.area_start_y) * OLED_SIZE_X + xOff; //指向要填充的位置
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + xOff; //指向要填充的位置
        yMin = disp_ctrl.area_start_y - yOff;
    }
    if (yMax > (disp_ctrl.area_end_y - yOff))
    {
        yMax = disp_ctrl.area_end_y - yOff;
    }

    for (int y = yMin; y <= yMax; y++)
    {
        for (int x = xMin; x <= xMax; x++)
        {
            //求取在原图中的坐标
            xSrc = co * (float)(x - img_w / 2) - si * (float)(y0 - y) + (float)((int)(img_w / 2));
            ySrc = si * (float)(img_w / 2 - x) + co * (float)(y - y0) + (float)((int)(y0));

            //如果在原图范围内
            if (ySrc >= 0.f && ySrc < img_h - 0.5f && xSrc >= 0.f && xSrc < img_w - 0.5f)
            {
                int xSmall = (int)xSrc;
                int xBig = (int)(xSrc + 0.99999f);
                int ySmall = (int)(ySrc);
                int yBig = (int)(ySrc + 0.99999f);
                a1 = (pSrc[ySmall * img_w + xSmall]);
                a2 = (pSrc[ySmall * img_w + xBig]);
                a3 = (pSrc[yBig * img_w + xSmall]);
                a4 = (pSrc[yBig * img_w + xBig]);
                float ux = xSrc - xSmall;
                float uy = ySrc - ySmall;

                //双线性插值
                float f1, f2, f3, f4;
                f1 = (1 - ux) * (1 - uy);
                f2 = (1 - ux) * uy;
                f3 = (1 - uy) * ux;
                f4 = ux * uy;
                float r = f1 * RGB565_GET_COLOR_R(a1) + f2 * RGB565_GET_COLOR_R(a3) + f3 * RGB565_GET_COLOR_R(a2) + f4 * RGB565_GET_COLOR_R(a4);
                float g = f1 * RGB565_GET_COLOR_G(a1) + f2 * RGB565_GET_COLOR_G(a3) + f3 * RGB565_GET_COLOR_G(a2) + f4 * RGB565_GET_COLOR_G(a4);
                float b = f1 * RGB565_GET_COLOR_B(a1) + f2 * RGB565_GET_COLOR_B(a3) + f3 * RGB565_GET_COLOR_B(a2) + f4 * RGB565_GET_COLOR_B(a4);
                //描点
                uint16_t temp_color = ((uint8_t)r << 11) | ((uint8_t)g << 5) | (uint8_t)b;
                // p_disp_buff[x] = temp_color;
                if (solid_colour == -1)
                {
                    p_disp_buff[x] = get_filter_color(temp_color, p_disp_buff[x]);
                }
                else if (solid_colour == -2)
                {
                    p_disp_buff[x] = get_multiply_color(temp_color, p_disp_buff[x]);
                }
                else
                {
                    p_disp_buff[x] = transparency_anti_aliasing(temp_color, p_disp_buff[x], solid_colour, transparency_by_white);
                }

                // if ((r < 12) && (g < 24) && (b < 12))
                // {
                //     p_disp_buff[x] = get_color_mixture3(temp_color, p_disp_buff[x]);
                // }
                // else
                // {
                //     p_disp_buff[x] = temp_color;
                // }
                // if (ignore_color != temp_color)
                // {
                //     //p_disp_buff[x] = get_color_mixture3(temp_color, p_disp_buff[x]);
                // }
            }
        }
        p_disp_buff += OLED_SIZE_X;
    }
}
/*********************************************************************************************
 * @brief 旋转图片
 * @param [in] p_image           图片
                        centre_xy          旋转中心,整个图片以这个点为中心旋转，xy指图片本身
                        centre_set_xy   旋转中心点放置在显示上的xy坐标点
                        degree              图片旋转角度
 * @warning 处理过程：计算原图在原位置旋转后的范围，对旋转后范围内的点依次计算在原图中的位置，计算其颜色
 ********************************************************************************************/
void disp_draw_img_rotate(const unsigned char *p_image, uint16_t ignore_color, uint32_t centre_xy, uint32_t centre_set_xy, uint16_t degree)
{
    disp_draw_img_rotate_with_solid(p_image, ignore_color, centre_xy, centre_set_xy, degree, -1, false);
}

/*********************************************************************************************
 * @brief 显示单个图片
 * @param [in] param1
 * @warning
 ********************************************************************************************/
void _disp_show_flash_img(uint8_t file_index, uint8_t start_x, uint8_t start_y, int img_sn)
{
    if (file_index >= DISP_LFS_FILE_USE_MAX)
    {
        return;
    }
    if (disp_ctrl.loop_cnt == 0)
    {
        disp_ctrl.common_file_w[file_index] = 0;
        disp_ctrl.common_file_h[file_index] = 0;
        //打开要显示的文件
        if (lfs_file_open(&little_fs, &disp_ctrl.common_file[file_index], lfs_file_get_name(img_sn), LFS_O_RDONLY) == LFS_ERR_OK)
        {
            uint8_t buff[4] = {0};
            if (lfs_file_read(&little_fs, &disp_ctrl.common_file[file_index], buff, sizeof(buff)) > 0)
            {
                disp_ctrl.common_file_w[file_index] = (buff[1] << 8) | buff[0];
                disp_ctrl.common_file_h[file_index] = (buff[3] << 8) | buff[2];
            }
            if ((disp_ctrl.common_file_w[file_index] > OLED_SIZE_X) || (disp_ctrl.common_file_h[file_index] > OLED_SIZE_Y))
            {
                disp_ctrl.common_file_w[file_index] = 0;
                disp_ctrl.common_file_h[file_index] = 0;
            }
            // disp_ctrl.common_file_x[file_index] = start_x;
            // disp_ctrl.common_file_y[file_index] = start_y;
        }
    }
    disp_draw_flash_image(start_x, start_y, disp_ctrl.common_file_w[file_index], disp_ctrl.common_file_h[file_index], &disp_ctrl.common_file[file_index], 4);
}

/*********************************************************************************************
 * @brief 显示主界面+两个界面交替闪烁
 * @warning
 ********************************************************************************************/
void _disp_show_com_img(show_com_img_cfg_t *p_cfg)
{
    if (disp_ctrl.auto_refresh_count == 0) //首次切换
    {
        if (disp_ctrl.loop_cnt == 0)
        {
            //打开要显示的文件
            if (lfs_file_open(&little_fs, &disp_ctrl.common_file[0], lfs_file_get_name(p_cfg->img_sn_full), LFS_O_RDONLY) == LFS_ERR_OK)
            {
                uint8_t buff[4];
                if (lfs_file_read(&little_fs, &disp_ctrl.common_file[0], buff, sizeof(buff)) > 0)
                {
                    disp_ctrl.common_file_w[0] = (buff[1] << 8) | buff[0];
                    disp_ctrl.common_file_h[0] = (buff[3] << 8) | buff[2];
                }
                if ((disp_ctrl.common_file_w[0] > OLED_SIZE_X) || (disp_ctrl.common_file_h[0] > OLED_SIZE_Y))
                {
                    disp_ctrl.common_file_w[0] = 0;
                    disp_ctrl.common_file_h[0] = 0;
                }
                // disp_ctrl.common_file_x[file_index] = p_cfg->img_x;
                // disp_ctrl.common_file_y[file_index] = p_cfg->img_y;
            }
            disp_ctrl.auto_refresh_time = p_cfg->reflash_ms;
            display_set_update_area(p_cfg->img1_x, p_cfg->img1_y, p_cfg->img1_w, p_cfg->img1_h);
        }
        disp_draw_flash_image(p_cfg->img_x, p_cfg->img_y, disp_ctrl.common_file_w[0], disp_ctrl.common_file_h[0], &disp_ctrl.common_file[0], 4);
    }
    else //自动刷新
    {
        if (disp_ctrl.loop_cnt == 0)
        {
            if (lfs_file_open(&little_fs, &disp_ctrl.common_file[0], lfs_file_get_name(p_cfg->img_sub_sn[disp_ctrl.auto_refresh_count % p_cfg->img_sub_cnt]), LFS_O_RDONLY) == LFS_ERR_OK)
            {
                uint8_t buff[4];
                if (lfs_file_read(&little_fs, &disp_ctrl.common_file[0], buff, sizeof(buff)) > 0)
                {
                    disp_ctrl.common_file_w[0] = (buff[1] << 8) | buff[0];
                    disp_ctrl.common_file_h[0] = (buff[3] << 8) | buff[2];
                }
                if ((disp_ctrl.common_file_w[0] > OLED_SIZE_X) || (disp_ctrl.common_file_h[0] > OLED_SIZE_Y))
                {
                    disp_ctrl.common_file_w[0] = 0;
                    disp_ctrl.common_file_h[0] = 0;
                }
                // disp_ctrl.common_file_x[file_index] = p_cfg->img_x;
                // disp_ctrl.common_file_y[file_index] = p_cfg->img_y;
            }
            disp_ctrl.auto_refresh_time = p_cfg->reflash_ms;
        }
        disp_draw_flash_image(p_cfg->img_x, p_cfg->img_y, disp_ctrl.common_file_w[0], disp_ctrl.common_file_h[0], &disp_ctrl.common_file[0], 4);
    }
}

/*********************************************************************************************
 * @brief 刷动态图
 * @warning
 ********************************************************************************************/
void _disp_show_flash_img_gif(const img_gif_com_t *p_cfg, int refresh_interval_ms)
{
    //设置刷新区域130x130的配置
    if ((disp_ctrl.loop_cnt == 0) && (disp_ctrl.auto_refresh_count == 0))
    {
        display_set_update_area(56, 34, 130, 130);
    }
    //背景色
    _disp_show_flash_img(DISP_LFS_FILE_INDEX_0, 56, 34, p_cfg->bg_sn);

    //图片
    int index = disp_ctrl.auto_refresh_count % p_cfg->gif_count;
    _disp_show_flash_img(DISP_LFS_FILE_INDEX_1, p_cfg->img[index].x, p_cfg->img[index].y, p_cfg->img[index].sn);

    disp_ctrl.auto_refresh_time = refresh_interval_ms;
}
/*********************************************************************************************
 * @brief 刷动态图
 * @warning
 ********************************************************************************************/
void _disp_show_flash_img_gif_56_56(const img_gif_com_t *p_cfg, int refresh_interval_ms)
{
    //设置刷新区域130x130的配置
    if ((disp_ctrl.loop_cnt == 0) && (disp_ctrl.auto_refresh_count == 0))
    {
        display_set_update_area(56, 56, 130, 130);
    }
    //背景色
    _disp_show_flash_img(DISP_LFS_FILE_INDEX_0, 56, 56, p_cfg->bg_sn);

    //图片
    int index = disp_ctrl.auto_refresh_count % p_cfg->gif_count;
    _disp_show_flash_img(DISP_LFS_FILE_INDEX_1, p_cfg->img[index].x, p_cfg->img[index].y, p_cfg->img[index].sn);

    disp_ctrl.auto_refresh_time = refresh_interval_ms;
}
/*********************************************************************************************
 * @brief 刷动态图 130X100的尺寸背景
 * @warning
 ********************************************************************************************/
void _disp_show_flash_img_gif_100(const img_gif_com_t *p_cfg, int refresh_interval_ms)
{
    //设置刷新区域130x130的配置
    if ((disp_ctrl.loop_cnt == 0) && (disp_ctrl.auto_refresh_count == 0))
    {
        display_set_update_area(56, 30, 130, 100);
    }
    //背景色
    _disp_show_flash_img(DISP_LFS_FILE_INDEX_0, 56, 30, p_cfg->bg_sn);

    //图片
    int index = disp_ctrl.auto_refresh_count % p_cfg->gif_count;
    _disp_show_flash_img(DISP_LFS_FILE_INDEX_1, p_cfg->img[index].x, p_cfg->img[index].y, p_cfg->img[index].sn);

    disp_ctrl.auto_refresh_time = refresh_interval_ms;
}
/*********************************************************************************************
 * @brief 刷动态图 130X100的尺寸背景-居中
 * @warning
 ********************************************************************************************/
void _disp_show_flash_img_gif_100_mid(const img_gif_com_t *p_cfg, int refresh_interval_ms)
{
#define Y_MOVE_DOWN_OFFSET (40)
    //设置刷新区域130x130的配置
    if ((disp_ctrl.loop_cnt == 0) && (disp_ctrl.auto_refresh_count == 0))
    {
        display_set_update_area(56, 30 + Y_MOVE_DOWN_OFFSET, 130, 100);
    }
    //背景色
    _disp_show_flash_img(DISP_LFS_FILE_INDEX_0, 56, 30 + Y_MOVE_DOWN_OFFSET, p_cfg->bg_sn);

    //图片
    int index = disp_ctrl.auto_refresh_count % p_cfg->gif_count;
    _disp_show_flash_img(DISP_LFS_FILE_INDEX_1, p_cfg->img[index].x, p_cfg->img[index].y + Y_MOVE_DOWN_OFFSET, p_cfg->img[index].sn);

    disp_ctrl.auto_refresh_time = refresh_interval_ms;
}

/*********************************************************************************************
 * @brief 居中显示一个大数字/
 * @param [in] x,y：靠左=第一个数字起始位置；居中=中心位置；靠右=右边界,最后数字的右边
 * @param [out] param2
 * @warning
 ********************************************************************************************/
void _disp_show_num_extend(disp_num_type_t type, uint8_t x, uint8_t y, uint32_t num, uint8_t width, const uint8_t *const IMAGE_USER_NUM_TAB[])
{
    uint8_t size_x;
    uint8_t temp8;
    size_x = width; //取字符大小--补充2个空格

    //计算起始显示位置
    temp8 = get_num_digit(num);
    int total_width = temp8 * size_x - 2; //减去2个空格的位置
    switch (type)
    {
    case DISP_NUM_TYPE_LEFT:
        if ((x + total_width) > OLED_SIZE_X) //判断溢出
        {
            break;
        }
        x = x + total_width - size_x;
        break;
    case DISP_NUM_TYPE_MID:
        if ((x < total_width / 2) || (((total_width / 2) + x) > OLED_SIZE_X)) //判断溢出
        {
            break;
        }
        x = x + total_width / 2 - size_x;
        break;
    case DISP_NUM_TYPE_RIGHT:
        if (x < total_width)
        {
            break;
        }
        x = x - size_x + 2; //补偿
    default:
        break;
    }

    //依次 从最低位->最高位显示
    while (temp8-- != 0)
    {
        disp_draw_user_image_ignore_color(x, y, 0, IMAGE_USER_NUM_TAB[num % 10]);
        num /= 10;
        x -= size_x;
    }
}
/*********************************************************************************************
 * @brief 居中显示一个大数字/
 * @param [in] x,y：靠左=第一个数字起始位置；居中=中心位置；靠右=右边界,最后数字的右边
 * @param [out] param2
 * @warning
 ********************************************************************************************/
void _disp_show_num_color_extend(disp_num_type_t type, uint8_t x, uint8_t y, uint32_t num, uint8_t width, uint16_t color, const uint8_t *const IMAGE_USER_NUM_TAB[])
{
    uint8_t size_x;
    uint8_t temp8;
    size_x = width; //取字符大小--补充2个空格

    //计算起始显示位置
    temp8 = get_num_digit(num);
    int total_width = temp8 * size_x - 2; //减去2个空格的位置
    switch (type)
    {
    case DISP_NUM_TYPE_LEFT:
        if ((x + total_width) > OLED_SIZE_X) //判断溢出
        {
            break;
        }
        x = x + total_width - size_x;
        break;
    case DISP_NUM_TYPE_MID:
        if ((x < total_width / 2) || (((total_width / 2) + x) > OLED_SIZE_X)) //判断溢出
        {
            break;
        }
        x = x + total_width / 2 - size_x;
        break;
    case DISP_NUM_TYPE_RIGHT:
        if (x < total_width)
        {
            break;
        }
        x = x - size_x + 2; //补偿
    default:
        break;
    }

    //依次 从最低位->最高位显示
    while (temp8-- != 0)
    {
        disp_draw_user_image_gray_lucency(x, y, color, IMAGE_USER_NUM_TAB[num % 10]);
        num /= 10;
        x -= size_x;
    }
}
/*********************************************************************************************
 * @brief   计算输入的字符串的合理起始x
 * @param [in] p_str 字符串
 * @warning
 ********************************************************************************************/
int disp_calc_start_x(disp_num_type_t type, int x, const char *p_string, int size)
{
    int total_width = strlen(p_string) * size;
    switch (type)
    {
    case DISP_NUM_TYPE_LEFT:
        if ((x + total_width) > OLED_SIZE_X) //溢出左移
        {
            x = OLED_SIZE_X - total_width;
            if (x < 0)
            {
                x = 0;
            }
            break;
        }
        break;
    case DISP_NUM_TYPE_MID:
        x = x - total_width / 2;
        if ((total_width + x) > OLED_SIZE_X) //右溢出-左移一些
        {
            x = OLED_SIZE_X - total_width;
        }
        if (x < 0) //左溢出
        {
            x = 0;
        }
        break;
    case DISP_NUM_TYPE_RIGHT:
        x = x - total_width;
        if (x < 0)
        {
            x = 0;
        }
    default:
        break;
    }
    return x;
}

/*********************************************************************************************
 * @brief   计算输入的字符串占用的像素点总宽度，不支持特殊的转译字符等
 * @param [in] p_str 字符串
 * @warning
 ********************************************************************************************/
static int disp_calc_font_string_pixel_width(const char *p_string, int size)
{
    int length = 0;
    uint32_t gb_code;
    int utf8_len;
    uint8_t *p_str_in = (uint8_t *)p_string;
    if ((extern_font_is_valid() == false) || ((size != 16) && (size != 24))) //假如字库打不开不显示
    {
        return 0;
    }
    extern_font_char_info_t font_temp;
    while (*p_str_in != '\0')
    {
        utf8_len = utf_to_unicode(p_str_in, &gb_code); //字符串转GB2312
        if (utf8_len == 0)                             //碰到解不了的数据直接结束
        {
            break;
        }
        p_str_in += utf8_len;
        if (size == 16)
        {
            extern_font16_get_bit_map(gb_code, (extern_font16_char_info_t *)&font_temp);
        }
        else
        {
            extern_font_get_bit_map(gb_code, &font_temp);
        }
        if (font_temp.width == 0)
        {
            break;
        }
        else
        {
            length += font_temp.width + FONT_SIZE_HORIZ_INTERVAL;
        }
    }
    return length;
}
/*********************************************************************************************
 * @brief   计算输入的字符串的合理起始x
 * @param [in] p_str 字符串
 * @warning
 ********************************************************************************************/
int disp_calc_font_string_start_x(disp_num_type_t type, int x, const char *p_string, int size)
{
    int total_width = disp_calc_font_string_pixel_width(p_string, size);
    switch (type)
    {
    case DISP_NUM_TYPE_LEFT:
        if ((x + total_width) > OLED_SIZE_X) //溢出左移
        {
            x = OLED_SIZE_X - total_width;
            if (x < 0)
            {
                x = 0;
            }
            break;
        }
        break;
    case DISP_NUM_TYPE_MID:
        x = x - total_width / 2;
        if ((total_width + x) > OLED_SIZE_X) //右溢出-左移一些
        {
            x = OLED_SIZE_X - total_width;
        }
        if (x < 0) //左溢出
        {
            x = 0;
        }
        break;
    case DISP_NUM_TYPE_RIGHT:
        x = x - total_width;
        if (x < 0)
        {
            x = 0;
        }
    default:
        break;
    }
    return x;
}

extern const unsigned char ASCII_8X16[];
/*********************************************************************************************
* @brief   显示字符串
 * @param [in] x ,y 字符起点
    @param [in] p_str 字符串
    @param [in] size  尺寸(8或16)
 * @warning  只支持字符串在同一行
 ********************************************************************************************/
void disp_show_ascii_string(uint8_t x, uint8_t y, char *p_str, uint8_t size, uint16_t color)
{
    uint8_t const *p_font;
    uint16_t *p_disp_buff;

    //判断和要显示的区域是否有重叠区域
    if ((disp_ctrl.area_start_y > (y + size - 1)) || (disp_ctrl.area_end_y < y))
    {
        return;
    }

    uint8_t width; //字符宽度
    if (size == 8)
    {
        width = 6;
        return;
    }
    else
    {
        width = 8;
    }

    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
    if (y >= disp_ctrl.area_start_y)
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y - disp_ctrl.area_start_y) * OLED_SIZE_X; //指向要填充的位置
        icon_start_y = 0;
    }
    else
    {
        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag]; //指向要填充的位置
        icon_start_y = disp_ctrl.area_start_y - y;
    }
    if (disp_ctrl.area_end_y >= (y + size - 1))
    {
        icon_end_y = size - 1;
    }
    else
    {
        icon_end_y = disp_ctrl.area_end_y - y;
    }

    while (*p_str != '\0')
    {
        if (x >= (OLED_SIZE_X - width)) // x溢出换行
        {
            break;
        }
        if (size == 8)
        {
            p_font = ASCII_8X16 + (*p_str - ' ') * 6;
        }
        else
        {
            p_font = ASCII_8X16 + (*p_str - ' ') * 16;
        }

        uint16_t *p_disp_temp = p_disp_buff + x;
        //展开icon
        if (icon_start_y < 8) //第一行
        {
            uint8_t b = icon_end_y > 7 ? 7 : icon_end_y;
            for (uint8_t a = icon_start_y; a <= b; a++)
            {
                uint8_t offset = 1 << a;
                for (uint8_t i = 0; i < width; i++)
                {
                    if (p_font[i] & offset)
                    {
                        p_disp_temp[i] = color;
                    }
                }
                p_disp_temp += OLED_SIZE_X;
            }
        }
        if (icon_end_y >= 8) //第二行
        {
            p_font += width;
            for (uint8_t a = icon_start_y > 8 ? icon_start_y : 8; a <= icon_end_y; a++)
            {
                uint8_t offset = 1 << (a - 8);
                for (uint8_t i = 0; i < width; i++)
                {
                    if (p_font[i] & offset)
                    {
                        p_disp_temp[i] = color;
                    }
                }
                p_disp_temp += OLED_SIZE_X;
            }
        }
        x += width;
        p_str++;
    }
}

/**
 * @brief
 *
 * @param x
 * @param y
 * @param num
 * @param width
 * @return int 绘制占用x轴到多少
 */
int disp_draw_user_image_num(int x, int y, int num, int width, uint8_t const *const *num_image)
{
    if (num < 0)
    {
        num = -num;
    }
    int digits = get_num_digit(num);
    int draw_x = 0;
    int draw_num = 0;
    int last_x = x + width * digits;
    for (int i = 0; i < digits; i++)
    {
        draw_num = num % 10;
        draw_x = x + width * (digits - 1 - i);
        disp_draw_user_image(draw_x, y, num_image[draw_num]);
        num /= 10;
    }
    return last_x;
}
int disp_draw_user_image_num_multiply(int x, int y, int num, int width, uint8_t const *const *num_image)
{
    if (num < 0)
    {
        num = -num;
    }
    int digits = get_num_digit(num);
    int draw_x = 0;
    int draw_num = 0;
    int last_x = x + width * digits;
    for (int i = 0; i < digits; i++)
    {
        draw_num = num % 10;
        draw_x = x + width * (digits - 1 - i);
        disp_draw_user_image_multiply(draw_x, y, num_image[draw_num]);
        num /= 10;
    }
    return last_x;
}
int disp_draw_user_image_num_filter_color(int x, int y, int num, int width, uint8_t const *const *num_image)
{
    if (num < 0)
    {
        num = -num;
    }
    int digits = get_num_digit(num);
    int draw_x = 0;
    int draw_num = 0;
    int last_x = x + width * digits;
    for (int i = 0; i < digits; i++)
    {
        draw_num = num % 10;
        draw_x = x + width * (digits - 1 - i);
        disp_draw_user_image_filter_color(draw_x, y, num_image[draw_num]);
        num /= 10;
    }
    return last_x;
}
int disp_draw_user_image_num_with_digits(int x, int y, int num, int digits, int width, uint8_t const *const *num_image)
{
    int draw_x = 0;
    int draw_num = 0;
    int last_x = x + width * digits;
    for (int i = 0; i < digits; i++)
    {
        draw_num = num % 10;
        draw_x = x + width * (digits - 1 - i);
        disp_draw_user_image(draw_x, y, num_image[draw_num]);
        num /= 10;
    }
    return last_x;
}
int disp_draw_user_image_num_with_digits_gray_lucency(int x, int y, int num, int digits, uint16_t color, int width, uint8_t const *const *num_image)
{
    int draw_x = 0;
    int draw_num = 0;
    int last_x = x + width * digits;
    for (int i = 0; i < digits; i++)
    {
        draw_num = num % 10;
        draw_x = x + width * (digits - 1 - i);
        disp_draw_user_image_gray_lucency(draw_x, y, color, num_image[draw_num]);
        num /= 10;
    }
    return last_x;
}
int disp_draw_user_image_num_with_digits_multiply(int x, int y, int num, int digits, int width, uint8_t const *const *num_image)
{
    if (num < 0)
    {
        num = -num;
    }
    int draw_x = 0;
    int draw_num = 0;
    int last_x = x + width * digits;
    for (int i = 0; i < digits; i++)
    {
        draw_num = num % 10;
        draw_x = x + width * (digits - 1 - i);
        disp_draw_user_image_multiply(draw_x, y, num_image[draw_num]);
        num /= 10;
    }
    return last_x;
}
int disp_draw_user_image_num_with_digits_filter_color(int x, int y, int num, int digits, int width, uint8_t const *const *num_image)
{
    if (num < 0)
    {
        num = -num;
    }
    int draw_x = 0;
    int draw_num = 0;
    int last_x = x + width * digits;
    for (int i = 0; i < digits; i++)
    {
        draw_num = num % 10;
        draw_x = x + width * (digits - 1 - i);
        disp_draw_user_image_filter_color(draw_x, y, num_image[draw_num]);
        num /= 10;
    }
    return last_x;
}
void _disp_show_flash_img_gif_all(const img_gif_com_t *p_cfg, uint8_t file_index)
{
    if (file_index >= DISP_LFS_FILE_USE_MAX)
    {
        return;
    }
    // //设置刷新区域130x130的配置
    // if ((disp_ctrl.loop_cnt == 0) && (disp_ctrl.auto_refresh_count == 0))
    // {
    //     display_set_update_area(56, 30, 130, 100);
    // }
    // //背景色
    // _disp_show_flash_img(DISP_LFS_FILE_INDEX_0, 56, 30, p_cfg->bg_sn);

    //图片
    int index = disp_ctrl.auto_refresh_count % p_cfg->gif_count;
    _disp_show_flash_img(file_index, p_cfg->img[index].x, p_cfg->img[index].y, p_cfg->img[index].sn);

    // disp_ctrl.auto_refresh_time = refresh_interval_ms;
}
typedef struct __disp_draw_user_image_cycle_percent_ext_param_t
{
    int center_x;
    int center_y;
    uint16_t transparent_color;
    uint16_t full_color;
    uint16_t empty_color;
    // float percent;
    float start_radian; // 0填满. 2.f*pi ,不填
    int end_x;
    int end_y;
    int inner_end_x;
    int inner_end_y;
} disp_draw_user_image_cycle_percent_ext_param_t;

void disp_draw_user_image_cycle_percent_callback(point_info_t const *point_info_t)
{
    disp_draw_user_image_cycle_percent_ext_param_t const *ext_param = (disp_draw_user_image_cycle_percent_ext_param_t const *)point_info_t->draw_ext_para;
    if (point_info_t->color == ext_param->transparent_color)
    {
        return;
    }
    int delta_x = point_info_t->x - ext_param->center_x;
    int delta_y = point_info_t->y - ext_param->center_y;
    bool is_draw = false;
    if (ext_param->start_radian >= 2.f * PI)
    {
        is_draw = false;
    }
    else if (ext_param->start_radian == 0.f)
    {
        is_draw = true;
    }
    else
    {
        if (ext_param->start_radian > 1.5f * PI)
        {
            if (delta_x >= 0)
            {
            }
            else if (delta_y <= 0)
            {
            }
            else if (delta_x >= ext_param->end_x && delta_y >= ext_param->end_y)
            {
                is_draw = true;
            }
        }
        else if (ext_param->start_radian > 1.0f * PI)
        {
            if (delta_x >= 0)
            {
            }
            else if (delta_y >= 0)
            {
                is_draw = true;
            }
            else
            {
                if (ext_param->start_radian > 1.25f * PI)
                {
                    if (delta_x <= ext_param->inner_end_x && delta_y >= ext_param->end_y)
                    {
                        is_draw = true;
                    }
                }
                else
                {
                    if (delta_x <= ext_param->inner_end_x)
                    {
                        is_draw = true;
                    }
                }
            }
        }
        else if (ext_param->start_radian > 0.5f * PI)
        {
            if (delta_x <= 0)
            {
                is_draw = true;
            }
            else if (delta_y >= 0)
            {
                is_draw = false;
            }
            else
            {
                if (ext_param->start_radian > 0.75f * PI)
                {
                    if (delta_x <= ext_param->end_x && delta_y <= ext_param->inner_end_y)
                    {
                        is_draw = true;
                    }
                }
                else
                {
                    if (delta_y <= ext_param->inner_end_y)
                    {
                        is_draw = true;
                    }
                }
            }
        }
        else if (ext_param->start_radian > 0.f)
        {
            if (delta_x <= 0)
            {
                is_draw = true;
            }
            else if (delta_y <= 0)
            {
                is_draw = true;
            }
            else
            {
                if (ext_param->start_radian > 0.25f * PI)
                {
                    if (delta_x >= ext_param->inner_end_x && delta_y <= ext_param->end_y)
                    {
                        is_draw = true;
                    }
                }
                else
                {
                    if (delta_x >= ext_param->inner_end_x)
                    {
                        is_draw = true;
                    }
                }
            }
        }
        else
        {
            is_draw = true;
        }
    }
    if (is_draw)
    {
        *(point_info_t->point) = get_multiply_color(point_info_t->color, ext_param->full_color);
    }
    else
    {
        *(point_info_t->point) = get_multiply_color(point_info_t->color, ext_param->empty_color);
    }
}

void disp_draw_user_image_cycle_percent(user_cycle_percent_param_t const *param)
{
    if (param == 0)
    {
        return;
    }
    if (param->base == 0)
    {
        return;
    }
    uint8_t const *p_user_image = param->base;
    int width = p_user_image[0] + (p_user_image[1] << 8);
    int height = p_user_image[2] + (p_user_image[3] << 8);
    int radius = width > height ? width / 2 : height / 2;

    int origin_x = 0;      // origin_x
    int origin_y = radius; // origin_y
    int inner_origin_y = radius - param->line_width;

    if (disp_ctrl.loop_cnt == 0)
    {
        float end_radian = 0.f;
        float start_radian = 0.f;
        int less_radius = width > height ? height / 2 : width / 2;
        if (param->target_num == 0 || param->target_num <= param->presently_num || param->presently_num < 0)
        {
            *(param->temp_2) = 0.f;
        }
        else if (param->presently_num == 0)
        {
            *(param->temp_2) = 2.f * PI;
        }
        else
        {
            float percent = (float)param->presently_num / param->target_num;
            float empty_radian = acosf((float)less_radius / radius);
            end_radian = 2.f * PI - empty_radian;
            start_radian = end_radian - 2.f * (PI - empty_radian) * percent;
            *(param->temp_2) = start_radian;
            // 0,y 逆时针旋转
            *(param->temp_0) = (float)origin_x * cosf(start_radian) + (float)origin_y * sinf(start_radian);
            *(param->temp_1) = (float)origin_y * cosf(start_radian) - (float)origin_x * sinf(start_radian);
            *(param->temp_3) = (float)origin_x * cosf(start_radian) + (float)inner_origin_y * sinf(start_radian);
            *(param->temp_4) = (float)inner_origin_y * cosf(start_radian) - (float)origin_x * sinf(start_radian);
        }
    }
    disp_draw_user_image_cycle_percent_ext_param_t const ext_param = {
        .center_x = param->x + radius,
        .center_y = param->y + radius,
        .transparent_color = param->transparent_color,
        .full_color = param->full_color,
        .empty_color = param->empty_color,
        // .percent = *(param->temp_2),
        .start_radian = *(param->temp_2),
        .end_x = *(param->temp_0),
        .end_y = *(param->temp_1),
        .inner_end_x = *(param->temp_3),
        .inner_end_y = *(param->temp_4),
    };
    disp_draw_user_image_ext(param->x, param->y, p_user_image, disp_draw_user_image_cycle_percent_callback, &ext_param);
}
// void disp_draw_flash_image_cycle_percent(flash_cycle_percent_param_t const *param)
//{
//    if (param == 0)
//    {
//        return;
//    }
//    if (param->presently_num == 0)
//    {
//        return;
//    }

//    int file_index = param->file_index;
//    int file_sn = param->file_sn;
//    if (disp_ctrl.loop_cnt == 0)
//    {
//        if (lfs_file_open(&little_fs, &disp_ctrl.common_file[file_index], lfs_file_get_name(file_sn), LFS_O_RDONLY) != LFS_ERR_OK)
//        {
//            return;
//        }
//        uint8_t buff[4];
//        if (lfs_file_read(&little_fs, &disp_ctrl.common_file[file_index], buff, sizeof(buff)) > 0)
//        {
//            disp_ctrl.common_file_w[file_index] = (buff[1] << 8) | buff[0];
//            disp_ctrl.common_file_h[file_index] = (buff[3] << 8) | buff[2];
//        }
//    }
//    if ((disp_ctrl.common_file_w[file_index] > OLED_SIZE_X) || (disp_ctrl.common_file_h[file_index] > OLED_SIZE_Y))
//    {
//        return;
//    }
//    {
//        int less_radius = disp_ctrl.common_file_w[file_index] > disp_ctrl.common_file_h[file_index] ? disp_ctrl.common_file_h[file_index] / 2 : disp_ctrl.common_file_w[file_index] / 2;
//        int radius = disp_ctrl.common_file_w[file_index] > disp_ctrl.common_file_h[file_index] ? disp_ctrl.common_file_w[file_index] / 2 : disp_ctrl.common_file_h[file_index] / 2;
//        float end_radian = 0.f;
//        float start_radian = 0.f;
//        if (param->target_num == 0 || param->target_num == param->presently_num)
//        {
//            start_radian = 0;
//            end_radian = 2 * PI;
//        }
//        else
//        {
//            float empty_radian = acosf((float)less_radius / radius);
//            end_radian = 2 * PI - empty_radian;
//            start_radian = end_radian - 2 * (PI - empty_radian) * param->presently_num / param->target_num;
//        }
//        draw_flash_radian_cycle_param_t const draw_param = {
//            .file_index = file_index,
//            .x = param->x,
//            .y = param->y,
//            .center_x = radius,
//            .center_y = radius,
//            .inner_diameter = 0,
//            .external_diameter = radius * 2,
//            .start_radian = start_radian,
//            .end_radian = end_radian,
//            .transparent_color = RGB565_COLOR_BLACK,
//            .temp_0 = param->temp_0,
//            .temp_1 = param->temp_1,
//        };
//        disp_draw_flash_radian_cycle(&draw_param);
//    }
//}

///**
// * @brief 绘制flash里的圆
// *      使用弧度 [0,2*pi)
// *      0,1 为0度，逆时针旋转
// *      使用屏幕坐标系
// *
// * @warning 未完全实现，没时间了
// */
// void disp_draw_flash_radian_cycle(draw_flash_radian_cycle_param_t const *param)
//{
//    lfs_file_t *const p_file = &disp_ctrl.common_file[param->file_index];
//    int const img_h = disp_ctrl.common_file_h[param->file_index];
//    int const img_w = disp_ctrl.common_file_w[param->file_index];
//    int const x = param->x;
//    int const y = param->y;
//    if ((disp_ctrl.area_start_y > (y + img_h - 1)) || (disp_ctrl.area_end_y < y))
//    {
//        return;
//    }
//    uint16_t *p_disp_buff; //指向显示的RAM

//    uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
//    if (y >= disp_ctrl.area_start_y)
//    {
//        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y - disp_ctrl.area_start_y) * OLED_SIZE_X; //指向要填充的位置
//        icon_start_y = 0;
//    }
//    else
//    {
//        p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag]; //指向要填充的位置
//        icon_start_y = disp_ctrl.area_start_y - y;
//    }
//    if (disp_ctrl.area_end_y >= (y + img_h - 1))
//    {
//        icon_end_y = img_h - 1;
//    }
//    else
//    {
//        icon_end_y = disp_ctrl.area_end_y - y;
//    }

//    //文件的偏移位置和显示需要的坐标不一致时重新设置文件偏移
//    if (p_file->off != (img_w * icon_start_y * 2 + 4))
//    {
//        lfs_file_seek(&little_fs, p_file, img_w * icon_start_y * 2 + 4, 0);
//    }

//    //判断
//    uint16_t color_buff[OLED_SIZE_X] = {0};

//    int draw_x = 0;
//    uint16_t color = 0;
//    int external_diameter_x = 0;
//    int external_diameter_y = param->external_diameter / 2;
//    if (disp_ctrl.loop_cnt == 0)
//    {
//#if 0
//#warning debug
//        *(param->temp_0) = external_diameter_x;
//        *(param->temp_1) = external_diameter_y;
//#else
//        *(param->temp_0) = (float)external_diameter_x * cosf(param->start_radian) + (float)external_diameter_y * sinf(param->start_radian);
//        *(param->temp_1) = (float)external_diameter_y * cosf(param->start_radian) - (float)external_diameter_x * sinf(param->start_radian);
//#endif
//    }
//    int external_diameter_end_x = *(param->temp_0);
//    int external_diameter_end_y = *(param->temp_1);
//    for (int draw_y = icon_start_y + y; draw_y <= (icon_end_y + y); draw_y++)
//    {
//        lfs_file_read(&little_fs, p_file, color_buff, img_w * 2);
//        int delta_y = draw_y - y - param->center_y;
//        for (int i = 0; i < img_w; i++)
//        {
//            if (color_buff[i] == param->transparent_color)
//            {
//                //!< 透明色判断
//                continue;
//            }
//            color = color_buff[i];
//            draw_x = x + i;
//            if (external_diameter_end_x == external_diameter_x && external_diameter_end_y == external_diameter_y)
//            {
//                p_disp_buff[draw_x] = color;
//            }
//            else
//            {
//                int delta_x = draw_x - x - param->center_x;
//                if (external_diameter_end_x <= 0)
//                {
//                    if (delta_x <= 0 && delta_y > external_diameter_end_y)
//                    {
//                        p_disp_buff[draw_x] = color;
//                    }
//                    else
//                    {
//                        continue;
//                    }
//                }
//                else
//                {
//                    if (delta_x > 0 && delta_y > external_diameter_end_y)
//                    {
//                        continue;
//                    }
//                    else
//                    {
//                        p_disp_buff[draw_x] = color;
//                    }
//                }
//            }
//        }
//        p_disp_buff += OLED_SIZE_X;
//    }
//}
// void disp_radian_cycle(draw_radian_cycle_param_t const *param)
// {
//     int const img_h = param->center_x * 2 + 1;
//     int const img_w = param->center_x * 2 + 1;
//     int const x = param->x;
//     int const y = param->y;
//     if ((disp_ctrl.area_start_y > (y + img_h - 1)) || (disp_ctrl.area_end_y < y))
//     {
//         return;
//     }
//     uint16_t *p_disp_buff; //指向显示的RAM

//     uint8_t icon_start_y, icon_end_y; //标记ICON需要显示的范围
//     if (y >= disp_ctrl.area_start_y)
//     {
//         p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag] + (y - disp_ctrl.area_start_y) * OLED_SIZE_X; //指向要填充的位置
//         icon_start_y = 0;
//     }
//     else
//     {
//         p_disp_buff = disp_ctrl.disp_buff[disp_ctrl.p_buff_flag]; //指向要填充的位置
//         icon_start_y = disp_ctrl.area_start_y - y;
//     }
//     if (disp_ctrl.area_end_y >= (y + img_h - 1))
//     {
//         icon_end_y = img_h - 1;
//     }
//     else
//     {
//         icon_end_y = disp_ctrl.area_end_y - y;
//     }

//     int draw_x = 0;
//     uint16_t color = 0;
//     for (int draw_y = icon_start_y + y; draw_y <= (icon_end_y + y); draw_y++)
//     {
//         for (int i = 0; i < img_w; i++)
//         {
//             color = param->color;
//             draw_x = x + i;
//             int delta_x = draw_x - x - param->center_x;
//             int delta_y = draw_y - y - param->center_y;
//             float distance = hypot(delta_x, delta_y);
//             if (distance >= param->external_diameter + 1.f || distance < param->inner_diameter - 1.f)
//             {
//                 //!< 距离判断
//                 continue;
//             }
//             if (param->start_radian != 0.f || param->end_radian != 0.f)
//             {
//                 float radian = atan2f(delta_x, delta_y);
//                 if (radian < 0)
//                 {
//                     radian += 2 * PI;
//                 }
//                 if (param->start_radian <= param->end_radian)
//                 {
//                     if (radian < param->start_radian || radian > param->end_radian)
//                     {
//                         if (param->second_color == RGB565_COLOR_BLACK)
//                         {
//                             continue;
//                         }
//                         else
//                         {
//                             color = param->second_color;
//                         }
//                     }
//                 }
//                 else
//                 {
//                     if (radian < param->start_radian && radian > param->end_radian)
//                     {
//                         if (param->second_color == RGB565_COLOR_BLACK)
//                         {
//                             continue;
//                         }
//                         else
//                         {
//                             color = param->second_color;
//                         }
//                     }
//                 }
//             }
//             float transparency = 1.f;
//             if (distance > param->external_diameter)
//             {
//                 transparency = 1 - (distance - param->external_diameter);
//             }
//             else if (distance < param->inner_diameter)
//             {
//                 transparency = 1 - (param->inner_diameter - distance);
//             }
//             if (transparency != 1.f)
//             {
//                 uint16_t red = RGB565_GET_COLOR_R(color) * transparency;
//                 uint16_t green = RGB565_GET_COLOR_G(color) * transparency;
//                 uint16_t blue = RGB565_GET_COLOR_B(color) * transparency;
//                 color = (red << 11) | (green << 5) | (blue);
//             }

//             p_disp_buff[draw_x] = color;
//         }
//         p_disp_buff += OLED_SIZE_X;
//     }
// }

void disp_show_user_string_middle(uint8_t start_x, int width, uint8_t start_y, char *p_string, uint8_t const *(*get_img)(char c))
{
    int const string_len = strlen(p_string);
    int const interval = 1;
    uint8_t const *p_img = 0;
    int draw_width = 0;
    for (int i = 0; i < string_len; i++)
    {
        if (get_img != 0)
        {
            p_img = get_img(p_string[i]);
            if (p_img)
            {
                draw_width += p_img[0] + (p_img[1] << 8) + interval;
            }
        }
    }
    draw_width -= interval;
    int draw_x = start_x + (width - draw_width) / 2;
    if (draw_x < start_x)
    {
        draw_x = start_x;
    }

    for (int i = 0; i < string_len; i++)
    {
        if (get_img != 0)
        {
            p_img = get_img(p_string[i]);
            if (p_img)
            {
                disp_draw_user_image(draw_x, start_y, p_img);
                draw_x += p_img[0] + (p_img[1] << 8) + interval;
            }
        }
    }
}

bool disp_show_resource_with_x_y_type(resource_type_t type, int file_index, int key, int default_temp_index, int x, int y)
{
    if (file_index >= DISP_LFS_FILE_USE_MAX)
    {
        return false;
    }
    if (disp_ctrl.loop_cnt == 0)
    {
        disp_ctrl.com_data.i_temp[default_temp_index] = open_resource_image(type, key, file_index, x, y);
    }
    if (disp_ctrl.com_data.i_temp[default_temp_index])
    {
        disp_draw_flash_image(disp_ctrl.common_file_x[file_index], disp_ctrl.common_file_y[file_index], disp_ctrl.common_file_w[file_index], disp_ctrl.common_file_h[file_index],
                              &disp_ctrl.common_file[file_index], 8);
        return true;
    }
    return false;
}
bool disp_show_localize(int file_index, int localize_key, int default_temp_index)
{
    return disp_show_localize_with_x_y(file_index, localize_key, default_temp_index, -1, -1);
}

bool disp_show_resource_with_x_y(int file_index, int key, int default_temp_index, int x, int y)
{
    return disp_show_resource_with_x_y_type(resource_type_resource, file_index, key, default_temp_index, x, y);
}

bool disp_show_localize_with_x_y(int file_index, int localize_key, int default_temp_index, int x, int y)
{
    return disp_show_resource_with_x_y_type(resource_type_localize, file_index, localize_key, default_temp_index, x, y);
}
